mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Added module (the first major plugin type) view(model) creation
This commit is contained in:
parent
8760b7f838
commit
e43d632adb
@ -104,6 +104,9 @@
|
|||||||
<Reference Include="Sanford.Multimedia.Midi, Version=6.4.2.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Sanford.Multimedia.Midi, Version=6.4.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Sanford.Multimedia.Midi.6.4.2\lib\net20\Sanford.Multimedia.Midi.dll</HintPath>
|
<HintPath>..\packages\Sanford.Multimedia.Midi.6.4.2\lib\net20\Sanford.Multimedia.Midi.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Stylet, Version=1.1.21.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Stylet.1.1.21\lib\net45\Stylet.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.AppContext, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
<Reference Include="System.AppContext, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll</HintPath>
|
<HintPath>..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll</HintPath>
|
||||||
@ -184,12 +187,8 @@
|
|||||||
<Compile Include="Constants.cs" />
|
<Compile Include="Constants.cs" />
|
||||||
<Compile Include="Exceptions\ArtemisCoreException.cs" />
|
<Compile Include="Exceptions\ArtemisCoreException.cs" />
|
||||||
<Compile Include="Exceptions\ArtemisPluginException.cs" />
|
<Compile Include="Exceptions\ArtemisPluginException.cs" />
|
||||||
<Compile Include="Models\PluginInfo.cs" />
|
|
||||||
<Compile Include="Ninject\CoreModule.cs" />
|
<Compile Include="Ninject\CoreModule.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Scripting.evaluator.cs" />
|
|
||||||
<Compile Include="Scripting.Extensions.cs" />
|
|
||||||
<Compile Include="Scripting.native.cs" />
|
|
||||||
<Compile Include="Services\CoreService.cs" />
|
<Compile Include="Services\CoreService.cs" />
|
||||||
<Compile Include="Services\Interfaces\IArtemisService.cs" />
|
<Compile Include="Services\Interfaces\IArtemisService.cs" />
|
||||||
<Compile Include="Services\Interfaces\ICoreService.cs" />
|
<Compile Include="Services\Interfaces\ICoreService.cs" />
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Artemis.Core.Models;
|
using Artemis.Plugins.Models;
|
||||||
|
|
||||||
namespace Artemis.Core.Exceptions
|
namespace Artemis.Core.Exceptions
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,295 +0,0 @@
|
|||||||
using CSScriptLibrary;
|
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.Remoting.Lifetime;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
// Read in more details about all aspects of CS-Script hosting in applications
|
|
||||||
// here: http://www.csscript.net/help/Script_hosting_guideline_.html
|
|
||||||
//
|
|
||||||
// This file contains samples for the script hosting scenarios requiring asynchronous script execution as well as unloading the
|
|
||||||
// scripts being executed.
|
|
||||||
// AsyncSamples
|
|
||||||
// Samples demonstrate the use of Async and Await mechanism available in C# 5 and higher. Note that the async method extensions
|
|
||||||
// cover the complete set of CSScript.Evaluator methods.
|
|
||||||
//
|
|
||||||
// UnloadingSamples
|
|
||||||
// Samples demonstrate the use of temporary AppDoamain for loading and executing dynamic C# code (script). It is the
|
|
||||||
// only mechanism available for unloading dynamically loaded assemblies. This is a well known CLR design limitation that leads to
|
|
||||||
// memory leaks if the assembly/script loaded in the caller AppDomain. The problem affects all C# script engines (e.g. Roslyn, CodeDom)
|
|
||||||
// and it cannot be solved by the engine itself thus CS-Script provides a work around in form of the MethodExtensions for the
|
|
||||||
// CSScript.Evaluator methods that are compatible with the unloading mechanism.
|
|
||||||
//
|
|
||||||
// Nevertheless you should try to avoid using remote AppDoamain unless you have to. It is very heavy and also imposes the serialization
|
|
||||||
// constrains.
|
|
||||||
//
|
|
||||||
// All samples rely on the compiler agnostic CSScript.Evaluator API.
|
|
||||||
namespace CSScriptEvaluatorExtensions
|
|
||||||
{
|
|
||||||
public class HostApp
|
|
||||||
{
|
|
||||||
public static void Test()
|
|
||||||
{
|
|
||||||
Console.WriteLine("---------------------------------------------");
|
|
||||||
Console.WriteLine("Testing asynchronous API");
|
|
||||||
Console.WriteLine("---------------------------------------------");
|
|
||||||
new AsyncSamples().RunAll();
|
|
||||||
Thread.Sleep(2000);
|
|
||||||
Console.WriteLine("\nPress 'Enter' to run uloading samples...");
|
|
||||||
Console.ReadLine();
|
|
||||||
Console.WriteLine("---------------------------------------------");
|
|
||||||
Console.WriteLine("Testing unloading API");
|
|
||||||
Console.WriteLine("---------------------------------------------");
|
|
||||||
new UnloadingSamples().RunAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
class AsyncSamples
|
|
||||||
{
|
|
||||||
public void RunAll()
|
|
||||||
{
|
|
||||||
Action<Action, string> run = (action, name) => { action(); Console.WriteLine(name); };
|
|
||||||
|
|
||||||
run(LoadDelegateAsync, "Start of " + nameof(LoadDelegateAsync));
|
|
||||||
run(LoadMethodAsync, "Start of " + nameof(LoadMethodAsync));
|
|
||||||
run(LoadCodeAsync, "Start of " + nameof(LoadCodeAsync));
|
|
||||||
run(CreateDelegateAsync, "Start of " + nameof(CreateDelegateAsync));
|
|
||||||
run(CompileCodeAsync, "Start of " + nameof(CompileCodeAsync));
|
|
||||||
run(RemoteAsynch, "Start of " + nameof(RemoteAsynch));
|
|
||||||
}
|
|
||||||
|
|
||||||
async void LoadDelegateAsync()
|
|
||||||
{
|
|
||||||
var product = await CSScript.Evaluator
|
|
||||||
.LoadDelegateAsync<Func<int, int, int>>(
|
|
||||||
@"int Product(int a, int b)
|
|
||||||
{
|
|
||||||
return a * b;
|
|
||||||
}");
|
|
||||||
|
|
||||||
Console.WriteLine(" End of {0}: {1}", nameof(LoadDelegateAsync), product(4, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void LoadMethodAsync()
|
|
||||||
{
|
|
||||||
dynamic script = await CSScript.Evaluator
|
|
||||||
.LoadMethodAsync(@"public int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
return a + b;
|
|
||||||
}
|
|
||||||
public int Div(int a, int b)
|
|
||||||
{
|
|
||||||
return a/b;
|
|
||||||
}");
|
|
||||||
|
|
||||||
Console.WriteLine(" End of {0}: {1}", nameof(LoadMethodAsync), script.Div(15, 3));
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void LoadCodeAsync()
|
|
||||||
{
|
|
||||||
//This use-case uses Interface Alignment and this requires all assemblies involved to have
|
|
||||||
//non-empty Assembly.Location
|
|
||||||
CSScript.GlobalSettings.InMemoryAssembly = false;
|
|
||||||
|
|
||||||
ICalc calc = await CSScript.Evaluator
|
|
||||||
.LoadCodeAsync<ICalc>(
|
|
||||||
@"using System;
|
|
||||||
public class Script
|
|
||||||
{
|
|
||||||
public int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
return a+b;
|
|
||||||
}
|
|
||||||
}");
|
|
||||||
|
|
||||||
Console.WriteLine(" End of {0}: {1}", nameof(LoadCodeAsync), calc.Sum(1, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void CreateDelegateAsync()
|
|
||||||
{
|
|
||||||
var product = await CSScript.Evaluator
|
|
||||||
.CreateDelegateAsync<int>(
|
|
||||||
@"int Product(int a, int b)
|
|
||||||
{
|
|
||||||
return a * b;
|
|
||||||
}");
|
|
||||||
|
|
||||||
Console.WriteLine(" End of {0}: {1}", nameof(CreateDelegateAsync), product(15, 3));
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void CompileCodeAsync()
|
|
||||||
{
|
|
||||||
Assembly script = await CSScript.Evaluator
|
|
||||||
.CompileCodeAsync(@"using System;
|
|
||||||
public class Script
|
|
||||||
{
|
|
||||||
public int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
return a+b;
|
|
||||||
}
|
|
||||||
}");
|
|
||||||
dynamic calc = script.CreateObject("*");
|
|
||||||
|
|
||||||
Console.WriteLine(" End of {0}: {1}", nameof(CompileCodeAsync), calc.Sum(15, 3));
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void RemoteAsynch()
|
|
||||||
{
|
|
||||||
var sum = await Task.Run(() =>
|
|
||||||
CSScript.Evaluator
|
|
||||||
.CreateDelegateRemotely<int>(
|
|
||||||
@"int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
return a+b;
|
|
||||||
}")
|
|
||||||
);
|
|
||||||
Console.WriteLine(" End of {0}: {1}", nameof(RemoteAsynch), sum(1, 2));
|
|
||||||
|
|
||||||
sum.UnloadOwnerDomain();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class UnloadingSamples
|
|
||||||
{
|
|
||||||
public void RunAll()
|
|
||||||
{
|
|
||||||
CreateDelegateRemotely();
|
|
||||||
LoadMethodRemotely();
|
|
||||||
LoadCodeRemotely();
|
|
||||||
LoadCodeRemotelyWithInterface();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CreateDelegateRemotely()
|
|
||||||
{
|
|
||||||
var sum = CSScript.Evaluator
|
|
||||||
.CreateDelegateRemotely<int>(@"int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
return a+b;
|
|
||||||
}");
|
|
||||||
|
|
||||||
Console.WriteLine("{0}: {1}", nameof(CreateDelegateRemotely), sum(15, 3));
|
|
||||||
|
|
||||||
sum.UnloadOwnerDomain();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadCodeRemotely()
|
|
||||||
{
|
|
||||||
// Class Calc doesn't implement ICals interface. Thus the compiled object cannot be typecasted into
|
|
||||||
// the interface and Evaluator will emit duck-typed assembly instead.
|
|
||||||
// But Mono and Roslyn build file-less assemblies, meaning that they cannot be used to build
|
|
||||||
// duck-typed proxies and CodeDomEvaluator needs to be used explicitly.
|
|
||||||
// Note class Calc also inherits from MarshalByRefObject. This is required for all object that
|
|
||||||
// are passed between AppDomain: they must inherit from MarshalByRefObject or be serializable.
|
|
||||||
|
|
||||||
//This use-case uses Interface Alignment and this requires all assemblies involved to have
|
|
||||||
//non-empty Assembly.Location
|
|
||||||
CSScript.GlobalSettings.InMemoryAssembly = false;
|
|
||||||
|
|
||||||
var script = CSScript.CodeDomEvaluator
|
|
||||||
.LoadCodeRemotely<ICalc>(
|
|
||||||
@"using System;
|
|
||||||
public class Calc : MarshalByRefObject
|
|
||||||
{
|
|
||||||
object t;
|
|
||||||
public int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
t = new Test();
|
|
||||||
return a+b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Test
|
|
||||||
{
|
|
||||||
~Test()
|
|
||||||
{
|
|
||||||
Console.WriteLine(""Domain is unloaded: ~Test()"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
");
|
|
||||||
|
|
||||||
Console.WriteLine("{0}: {1}", nameof(LoadCodeRemotely), script.Sum(15, 3));
|
|
||||||
|
|
||||||
script.UnloadOwnerDomain();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadCodeRemotelyWithInterface()
|
|
||||||
{
|
|
||||||
// Note class Calc also inherits from MarshalByRefObject. This is required for all object that
|
|
||||||
// are passed between AppDomain: they must inherit from MarshalByRefObject or be serializable.
|
|
||||||
var script = CSScript.Evaluator
|
|
||||||
.LoadCodeRemotely<ICalc>(
|
|
||||||
@"using System;
|
|
||||||
public class Calc : MarshalByRefObject, CSScriptEvaluatorExtensions.ICalc
|
|
||||||
{
|
|
||||||
public int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
return a+b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
");
|
|
||||||
|
|
||||||
Console.WriteLine("{0}: {1}", nameof(LoadCodeRemotelyWithInterface), script.Sum(15, 3));
|
|
||||||
|
|
||||||
script.UnloadOwnerDomain();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadMethodRemotely()
|
|
||||||
{
|
|
||||||
// LoadMethodRemotely is essentially the same as LoadCodeRemotely. It just deals not with the
|
|
||||||
// whole class definition but a single method(s) only. And the rest of the class definition is
|
|
||||||
// added automatically by CS-Script. The auto-generated class declaration also indicates
|
|
||||||
// that the class implements ICalc interface. Meaning that it will trigger compile error
|
|
||||||
// if the set of methods in the script code doesn't implement all interface members.
|
|
||||||
|
|
||||||
//This use-case uses Interface Alignment and this requires all assemblies involved to have
|
|
||||||
//non-empty Assembly.Location
|
|
||||||
CSScript.GlobalSettings.InMemoryAssembly = false;
|
|
||||||
|
|
||||||
var script = CSScript.Evaluator
|
|
||||||
.LoadMethodRemotely<IFullCalc>(
|
|
||||||
@"public int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
return a+b;
|
|
||||||
}
|
|
||||||
public int Sub(int a, int b)
|
|
||||||
{
|
|
||||||
return a-b;
|
|
||||||
}");
|
|
||||||
|
|
||||||
Console.WriteLine("{0}: {1}", nameof(LoadMethodRemotely), script.Sum(15, 3));
|
|
||||||
|
|
||||||
script.UnloadOwnerDomain();
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodDelegate sum;
|
|
||||||
ClientSponsor sumSponsor;
|
|
||||||
|
|
||||||
public void KeepRemoteObjectAlive()
|
|
||||||
{
|
|
||||||
sum = CSScript.Evaluator
|
|
||||||
.CreateDelegateRemotely(@"int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
return a+b;
|
|
||||||
}");
|
|
||||||
|
|
||||||
//Normally remote objects are disposed if they are not accessed withing a default timeout period.
|
|
||||||
//It is not even enough to keep transparent proxies or their wrappers (e.g. 'sum') referenced.
|
|
||||||
//To prevent GC collection in the remote domain use .NET ClientSponsor mechanism as below.
|
|
||||||
sumSponsor = sum.ExtendLifeFromMinutes(30);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ICalc
|
|
||||||
{
|
|
||||||
int Sum(int a, int b);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IFullCalc
|
|
||||||
{
|
|
||||||
int Sum(int a, int b);
|
|
||||||
|
|
||||||
int Sub(int a, int b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,345 +0,0 @@
|
|||||||
using CSScriptLibrary;
|
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
// Read in more details about all aspects of CS-Script hosting in applications
|
|
||||||
// here: http://www.csscript.net/help/Script_hosting_guideline_.html
|
|
||||||
//
|
|
||||||
// This file contains samples for the script hosting scenarios relying on CS-Script Evaluator interface (API).
|
|
||||||
// This API is a unified generic interface allowing dynamic switch of the underlying compiling services (Mono, Roslyn, CodeDom)
|
|
||||||
// without the need for changing the hosting code.
|
|
||||||
//
|
|
||||||
// Apart from Evaluator (compiler agnostic) API CS-Script offers alternative hosting model: CS-Script Native,
|
|
||||||
// which relies solely on CodeDom compiler. CS-Script Native offers some features that are not available with CS-Script Evaluator
|
|
||||||
// (e.g. script unloading).
|
|
||||||
//
|
|
||||||
// The choice of the underlying compiling engine (e.g. Mono vs CodeDom) when using CS-Script Evaluator is always dictated by the
|
|
||||||
// specifics of the hosting scenario. Thanks to in-process compiler hosting, Mono and Roslyn demonstrate much better compiling
|
|
||||||
// performance comparing to CodeDom engine. However they don't allow script debugging and caching easily supported with CodeDom.
|
|
||||||
// Mono and particularly Roslyn also leas create more memory pressure due to the higher volume of the temp assemblies loaded into
|
|
||||||
// the hosting AppDomain. Roslyn (at least CSharp.Scripting-v1.2.0.0) also has very high initial loading overhead up to 4 seconds.
|
|
||||||
//
|
|
||||||
// One of the possible approaches would be to use EvaluatorEngine.CodeDom during the active development and later on switch to Mono/Roslyn.
|
|
||||||
|
|
||||||
namespace CSScriptEvaluatorApi
|
|
||||||
{
|
|
||||||
public class HostApp
|
|
||||||
{
|
|
||||||
public static void Test()
|
|
||||||
{
|
|
||||||
// Just in case clear AlternativeCompiler so it is not set to Roslyn or anything else by
|
|
||||||
// the CS-Script installed (if any) on the host OS
|
|
||||||
CSScript.GlobalSettings.UseAlternativeCompiler = null;
|
|
||||||
|
|
||||||
var samples = new EvaluatorSamples();
|
|
||||||
|
|
||||||
Console.WriteLine("Testing compiling services");
|
|
||||||
Console.WriteLine("---------------------------------------------");
|
|
||||||
|
|
||||||
CSScript.EvaluatorConfig.Engine = EvaluatorEngine.Mono;
|
|
||||||
Console.WriteLine(CSScript.Evaluator.GetType().Name + "...");
|
|
||||||
samples.RunAll();
|
|
||||||
|
|
||||||
Console.WriteLine("---------------------------------------------");
|
|
||||||
|
|
||||||
CSScript.EvaluatorConfig.Engine = EvaluatorEngine.Roslyn;
|
|
||||||
Console.WriteLine(CSScript.Evaluator.GetType().Name + "...");
|
|
||||||
samples.RunAll();
|
|
||||||
|
|
||||||
Console.WriteLine("---------------------------------------------");
|
|
||||||
|
|
||||||
CSScript.EvaluatorConfig.Engine = EvaluatorEngine.CodeDom;
|
|
||||||
Console.WriteLine(CSScript.Evaluator.GetType().Name + "...");
|
|
||||||
|
|
||||||
samples.RunAll();
|
|
||||||
|
|
||||||
//samples.DebugTest(); //uncomment if want to fire an assertion during the script execution
|
|
||||||
|
|
||||||
//Profile(); //uncomment if want to test performance of the engines
|
|
||||||
}
|
|
||||||
|
|
||||||
class EvaluatorSamples
|
|
||||||
{
|
|
||||||
public void RunAll()
|
|
||||||
{
|
|
||||||
Action<Action, string> run = (action, name) => { action(); Console.WriteLine(name + " - OK"); };
|
|
||||||
|
|
||||||
run(CompileMethod_Instance, nameof(CompileMethod_Instance));
|
|
||||||
run(CompileMethod_Static, nameof(CompileMethod_Static));
|
|
||||||
run(CreateDelegate, nameof(CreateDelegate));
|
|
||||||
run(LoadDelegate, nameof(LoadDelegate));
|
|
||||||
run(LoadCode, nameof(LoadCode));
|
|
||||||
run(LoadMethod, nameof(LoadMethod));
|
|
||||||
run(LoadMethodWithInterface, nameof(LoadMethodWithInterface));
|
|
||||||
run(LoadCode_WithInterface, nameof(LoadCode_WithInterface));
|
|
||||||
run(LoadCode_WithDuckTypedInterface, nameof(LoadCode_WithDuckTypedInterface));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CompileMethod_Instance()
|
|
||||||
{
|
|
||||||
// 1- CompileMethod wraps method into a class definition and returns compiled assembly
|
|
||||||
// 2 - CreateObject creates instance of a first class in the assembly
|
|
||||||
|
|
||||||
dynamic script = CSScript.Evaluator
|
|
||||||
.CompileMethod(@"int Sqr(int data)
|
|
||||||
{
|
|
||||||
return data * data;
|
|
||||||
}")
|
|
||||||
.CreateObject("*");
|
|
||||||
|
|
||||||
var result = script.Sqr(7);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CompileMethod_Static()
|
|
||||||
{
|
|
||||||
// 1 - CompileMethod wraps method into a class definition and returns compiled assembly
|
|
||||||
// 2 - GetStaticMethod returns duck-typed delegate that accepts 'params object[]' arguments
|
|
||||||
// Note: GetStaticMethodWithArgs can be replaced with a more convenient/shorter version
|
|
||||||
// that takes the object instead of the Type and then queries objects type internally:
|
|
||||||
// "GetStaticMethod("*.Test", data)"
|
|
||||||
|
|
||||||
var test = CSScript.Evaluator
|
|
||||||
.CompileMethod(@"using CSScriptEvaluatorApi;
|
|
||||||
static void Test(InputData data)
|
|
||||||
{
|
|
||||||
data.Index = GetIndex();
|
|
||||||
}
|
|
||||||
static int GetIndex()
|
|
||||||
{
|
|
||||||
return Environment.TickCount;
|
|
||||||
}")
|
|
||||||
.GetStaticMethodWithArgs("*.Test", typeof(InputData));
|
|
||||||
|
|
||||||
var data = new InputData();
|
|
||||||
test(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CreateDelegate()
|
|
||||||
{
|
|
||||||
// Wraps method into a class definition, compiles it and loads the compiled assembly.
|
|
||||||
// It returns duck-typed delegate. A delegate with 'params object[]' arguments and
|
|
||||||
// without any specific return type.
|
|
||||||
|
|
||||||
var sqr = CSScript.Evaluator
|
|
||||||
.CreateDelegate(@"int Sqr(int a)
|
|
||||||
{
|
|
||||||
return a * a;
|
|
||||||
}");
|
|
||||||
|
|
||||||
var r = sqr(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadDelegate()
|
|
||||||
{
|
|
||||||
// Wraps method into a class definition, loads the compiled assembly
|
|
||||||
// and returns the method delegate for the method, which matches the delegate specified
|
|
||||||
// as the type parameter of LoadDelegate
|
|
||||||
|
|
||||||
var product = CSScript.Evaluator
|
|
||||||
.LoadDelegate<Func<int, int, int>>(
|
|
||||||
@"int Product(int a, int b)
|
|
||||||
{
|
|
||||||
return a * b;
|
|
||||||
}");
|
|
||||||
|
|
||||||
int result = product(3, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadCode()
|
|
||||||
{
|
|
||||||
// LoadCode compiles code and returns instance of a first class
|
|
||||||
// in the compiled assembly
|
|
||||||
|
|
||||||
dynamic script = CSScript.Evaluator
|
|
||||||
.LoadCode(@"using System;
|
|
||||||
public class Script
|
|
||||||
{
|
|
||||||
public int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
return a+b;
|
|
||||||
}
|
|
||||||
}");
|
|
||||||
|
|
||||||
int result = script.Sum(1, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadMethod()
|
|
||||||
{
|
|
||||||
// LoadMethod compiles code and returns instance of a first class
|
|
||||||
// in the compiled assembly.
|
|
||||||
// LoadMethod is essentially the same as LoadCode. It just deals not with the
|
|
||||||
// whole class definition but a single method(s) only. And the rest of the class definition is
|
|
||||||
// added automatically by CS-Script.
|
|
||||||
// 'public' is optional as it will be injected if the code doesn't start with it.
|
|
||||||
dynamic script = CSScript.Evaluator
|
|
||||||
.LoadMethod(@"using System;
|
|
||||||
public int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
return a+b;
|
|
||||||
}");
|
|
||||||
|
|
||||||
int result = script.Sum(1, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadMethodWithInterface()
|
|
||||||
{
|
|
||||||
// LoadMethod compiles code and returns instance of a first class
|
|
||||||
// in the compiled assembly.
|
|
||||||
// LoadMethod is essentially the same as LoadCode. It just deals not with the
|
|
||||||
// whole class definition but a single method(s) only. And the rest of the class definition is
|
|
||||||
// added automatically by CS-Script. The auto-generated class declaration also indicates
|
|
||||||
// that the class implements ICalc interface. Meaning that it will trigger compile error
|
|
||||||
// if the set of methods in the script code doesn't implement all interface members.
|
|
||||||
|
|
||||||
//This use-case uses Interface Alignment and this requires all assemblies involved to have
|
|
||||||
//non-empty Assembly.Location
|
|
||||||
CSScript.GlobalSettings.InMemoryAssembly = false;
|
|
||||||
|
|
||||||
ICalc script = CSScript.Evaluator
|
|
||||||
.LoadMethod<ICalc>(
|
|
||||||
@"int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
return a+b;
|
|
||||||
}");
|
|
||||||
|
|
||||||
int result = script.Sum(1, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadCode_WithInterface()
|
|
||||||
{
|
|
||||||
// 1 - LoadCode compiles code and returns instance of a first class in the compiled assembly
|
|
||||||
// 2 - The script class implements host app interface so the returned object can be type casted into it
|
|
||||||
|
|
||||||
var script = (ICalc)CSScript.Evaluator
|
|
||||||
.LoadCode(@"using System;
|
|
||||||
public class Script : CSScriptEvaluatorApi.ICalc
|
|
||||||
{
|
|
||||||
public int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
return a+b;
|
|
||||||
}
|
|
||||||
}");
|
|
||||||
|
|
||||||
int result = script.Sum(1, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadCode_WithDuckTypedInterface()
|
|
||||||
{
|
|
||||||
// 1 - LoadCode compiles code and returns instance of a first class in the compiled assembly
|
|
||||||
// 2- The script class doesn't implement host app interface but it can still be aligned to
|
|
||||||
// one as long at it implements the interface members
|
|
||||||
|
|
||||||
//This use-case uses Interface Alignment and this requires all assemblies involved to have
|
|
||||||
//non-empty Assembly.Location
|
|
||||||
CSScript.GlobalSettings.InMemoryAssembly = false;
|
|
||||||
|
|
||||||
ICalc script = CSScript.MonoEvaluator
|
|
||||||
.LoadCode<ICalc>(@"using System;
|
|
||||||
public class Script
|
|
||||||
{
|
|
||||||
public int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
return a+b;
|
|
||||||
}
|
|
||||||
}");
|
|
||||||
|
|
||||||
int result = script.Sum(1, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PerformanceTest(int count = -1)
|
|
||||||
{
|
|
||||||
var code = @"int Sqr(int a)
|
|
||||||
{
|
|
||||||
return a * a;
|
|
||||||
}";
|
|
||||||
|
|
||||||
if (count != -1)
|
|
||||||
code += "//" + count; //this unique extra code comment ensures the code to be compiled cannot be cached
|
|
||||||
|
|
||||||
dynamic script = CSScript.Evaluator
|
|
||||||
.CompileMethod(code)
|
|
||||||
.CreateObject("*");
|
|
||||||
|
|
||||||
var r = script.Sqr(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DebugTest()
|
|
||||||
{
|
|
||||||
//pops up an assertion dialog
|
|
||||||
|
|
||||||
CSScript.EvaluatorConfig.DebugBuild = true;
|
|
||||||
CSScript.EvaluatorConfig.Engine = EvaluatorEngine.CodeDom;
|
|
||||||
|
|
||||||
dynamic script = CSScript.Evaluator
|
|
||||||
.LoadCode(@"using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
public class Script
|
|
||||||
{
|
|
||||||
public int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
Debug.Assert(false,""Testing CS-Script debugging..."");
|
|
||||||
return a+b;
|
|
||||||
}
|
|
||||||
}");
|
|
||||||
|
|
||||||
var r = script.Sum(3, 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Profile()
|
|
||||||
{
|
|
||||||
var sw = new Stopwatch();
|
|
||||||
var samples = new EvaluatorSamples();
|
|
||||||
var count = 20;
|
|
||||||
var inxed = 0;
|
|
||||||
bool preventCaching = false;
|
|
||||||
|
|
||||||
Action run = () =>
|
|
||||||
{
|
|
||||||
sw.Restart();
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
if (preventCaching)
|
|
||||||
samples.PerformanceTest(inxed++);
|
|
||||||
else
|
|
||||||
samples.PerformanceTest();
|
|
||||||
|
|
||||||
Console.WriteLine(CSScript.Evaluator.GetType().Name + ": " + sw.ElapsedMilliseconds);
|
|
||||||
};
|
|
||||||
|
|
||||||
Action runAll = () =>
|
|
||||||
{
|
|
||||||
Console.WriteLine("\n---------------------------------------------");
|
|
||||||
Console.WriteLine($"Caching enabled: {!preventCaching}\n");
|
|
||||||
|
|
||||||
CSScript.EvaluatorConfig.Engine = EvaluatorEngine.Mono;
|
|
||||||
run();
|
|
||||||
|
|
||||||
CSScript.EvaluatorConfig.Engine = EvaluatorEngine.CodeDom;
|
|
||||||
run();
|
|
||||||
|
|
||||||
CSScript.EvaluatorConfig.Engine = EvaluatorEngine.Roslyn;
|
|
||||||
run();
|
|
||||||
};
|
|
||||||
|
|
||||||
RoslynEvaluator.LoadCompilers(); //Roslyn is extremely heavy so exclude startup time from profiling
|
|
||||||
|
|
||||||
Console.WriteLine("Testing performance");
|
|
||||||
|
|
||||||
preventCaching = true;
|
|
||||||
runAll();
|
|
||||||
|
|
||||||
preventCaching = false;
|
|
||||||
runAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ICalc
|
|
||||||
{
|
|
||||||
int Sum(int a, int b);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class InputData
|
|
||||||
{
|
|
||||||
public int Index = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,354 +0,0 @@
|
|||||||
using CSScriptLibrary;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.IO;
|
|
||||||
using csscript;
|
|
||||||
using System.CodeDom.Compiler;
|
|
||||||
|
|
||||||
// Read in more details about all aspects of CS-Script hosting in applications
|
|
||||||
// here: http://www.csscript.net/help/Script_hosting_guideline_.html
|
|
||||||
//
|
|
||||||
// This file contains samples for the script hosting scenarios relying on CS-Script Native interface (API).
|
|
||||||
// This API is a compiler specific interface, which relies solely on CodeDom compiler. In most of the cases
|
|
||||||
// CS-Script Native model is the most flexible and natural choice
|
|
||||||
//
|
|
||||||
// Apart from Native API CS-Script offers alternative hosting model: CS-Script Evaluator, which provides
|
|
||||||
// a unified generic interface allowing dynamic switch the underlying compiling services (Mono, Roslyn, CodeDom)
|
|
||||||
// without the need for changing the hosting code.
|
|
||||||
//
|
|
||||||
// The Native interface is the original API that was designed to take maximum advantage of the dynamic C# code
|
|
||||||
// execution with CodeDom. The original implementation of this API was developed even before any compiler-as-service
|
|
||||||
// solution became available. Being based solely on CodeDOM the API doesn't utilize neither Mono nor Roslyn
|
|
||||||
// scripting solutions. Despite that CS-Script Native is the most mature, powerful and flexible API available with CS-Script.
|
|
||||||
//
|
|
||||||
// Native interface allows some unique features that are not available with CS-Script Evaluator:
|
|
||||||
// - Debugging scripts
|
|
||||||
// - Script caching
|
|
||||||
// - Script unloading
|
|
||||||
|
|
||||||
namespace CSScriptNativeApi
|
|
||||||
{
|
|
||||||
public class HostApp
|
|
||||||
{
|
|
||||||
public static void Test()
|
|
||||||
{
|
|
||||||
var host = new HostApp();
|
|
||||||
host.Log("Testing compiling services CS-Script Native API");
|
|
||||||
Console.WriteLine("---------------------------------------------");
|
|
||||||
|
|
||||||
CodeDomSamples.LoadMethod_Instance();
|
|
||||||
CodeDomSamples.LoadMethod_Static();
|
|
||||||
CodeDomSamples.LoadDelegate();
|
|
||||||
CodeDomSamples.CreateAction();
|
|
||||||
CodeDomSamples.CreateFunc();
|
|
||||||
CodeDomSamples.LoadCode();
|
|
||||||
CodeDomSamples.LoadCode_WithInterface(host);
|
|
||||||
CodeDomSamples.LoadCode_WithDuckTypedInterface(host);
|
|
||||||
CodeDomSamples.ExecuteAndUnload();
|
|
||||||
//CodeDomSamples.DebugTest(); //uncomment if want to fire an assertion during the script execution
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CodeDomSamples
|
|
||||||
{
|
|
||||||
public static void LoadMethod_Instance()
|
|
||||||
{
|
|
||||||
// 1- LoadMethod wraps method into a class definition, compiles it and returns loaded assembly
|
|
||||||
// 2 - CreateObject creates instance of a first class in the assembly
|
|
||||||
|
|
||||||
dynamic script = CSScript.LoadMethod(@"int Sqr(int data)
|
|
||||||
{
|
|
||||||
return data * data;
|
|
||||||
}")
|
|
||||||
.CreateObject("*");
|
|
||||||
|
|
||||||
var result = script.Sqr(7);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LoadMethod_Static()
|
|
||||||
{
|
|
||||||
// 1 - LoadMethod wraps method into a class definition, compiles it and returns loaded assembly
|
|
||||||
// 2 - GetStaticMethod returns first found static method as a duck-typed delegate that
|
|
||||||
// accepts 'params object[]' arguments
|
|
||||||
//
|
|
||||||
// Note: you can use GetStaticMethodWithArgs for higher precision method search: GetStaticMethodWithArgs("*.SayHello", typeof(string));
|
|
||||||
var sayHello = CSScript.LoadMethod(@"static void SayHello(string greeting)
|
|
||||||
{
|
|
||||||
Console.WriteLine(greeting);
|
|
||||||
}")
|
|
||||||
.GetStaticMethod();
|
|
||||||
|
|
||||||
sayHello("Hello World!");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LoadDelegate()
|
|
||||||
{
|
|
||||||
// LoadDelegate wraps method into a class definition, compiles it and loads the compiled assembly.
|
|
||||||
// It returns the method delegate for the method, which matches the delegate specified
|
|
||||||
// as the type parameter of LoadDelegate
|
|
||||||
|
|
||||||
// The 'using System;' is optional; it demonstrates how to specify 'using' in the method-only syntax
|
|
||||||
|
|
||||||
var sayHello = CSScript.LoadDelegate<Action<string>>(
|
|
||||||
@"void SayHello(string greeting)
|
|
||||||
{
|
|
||||||
Console.WriteLine(greeting);
|
|
||||||
}");
|
|
||||||
|
|
||||||
sayHello("Hello World!");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void CreateAction()
|
|
||||||
{
|
|
||||||
// Wraps method into a class definition, compiles it and loads the compiled assembly.
|
|
||||||
// It returns duck-typed delegate. A delegate with 'params object[]' arguments and
|
|
||||||
// without any specific return type.
|
|
||||||
|
|
||||||
var sayHello = CSScript.CreateAction(@"void SayHello(string greeting)
|
|
||||||
{
|
|
||||||
Console.WriteLine(greeting);
|
|
||||||
}");
|
|
||||||
|
|
||||||
sayHello("Hello World!");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void CreateFunc()
|
|
||||||
{
|
|
||||||
// Wraps method into a class definition, compiles it and loads the compiled assembly.
|
|
||||||
// It returns duck-typed delegate. A delegate with 'params object[]' arguments and
|
|
||||||
// int as a return type.
|
|
||||||
|
|
||||||
var Sqr = CSScript.CreateFunc<int>(@"int Sqr(int a)
|
|
||||||
{
|
|
||||||
return a * a;
|
|
||||||
}");
|
|
||||||
int r = Sqr(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LoadCode()
|
|
||||||
{
|
|
||||||
// LoadCode compiles code and returns instance of a first class
|
|
||||||
// in the compiled assembly
|
|
||||||
|
|
||||||
dynamic script = CSScript.LoadCode(@"using System;
|
|
||||||
public class Script
|
|
||||||
{
|
|
||||||
public int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
return a+b;
|
|
||||||
}
|
|
||||||
}")
|
|
||||||
.CreateObject("*");
|
|
||||||
|
|
||||||
int result = script.Sum(1, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LoadCodeWithConfig()
|
|
||||||
{
|
|
||||||
// LoadCode compiles code and returns instance of a first class
|
|
||||||
// in the compiled assembly
|
|
||||||
|
|
||||||
string file = Path.GetTempFileName();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File.WriteAllText(file, @"using System;
|
|
||||||
public class Script
|
|
||||||
{
|
|
||||||
public int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
return a+b;
|
|
||||||
}
|
|
||||||
}");
|
|
||||||
|
|
||||||
var settings = new Settings();
|
|
||||||
//settings = null; // set to null to foll back to defaults
|
|
||||||
|
|
||||||
dynamic script = CSScript.LoadWithConfig(file, null, false, settings, "/define:TEST")
|
|
||||||
.CreateObject("*");
|
|
||||||
|
|
||||||
int result = script.Sum(1, 2);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (File.Exists(file))
|
|
||||||
File.Delete(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LoadCode_WithInterface(HostApp host)
|
|
||||||
{
|
|
||||||
// 1 - LoadCode compiles code and returns instance of a first class in the compiled assembly.
|
|
||||||
// 2 - The script class implements host app interface so the returned object can be type casted into it.
|
|
||||||
// 3 - In this sample host object is passed into script routine.
|
|
||||||
|
|
||||||
var calc = (ICalc) CSScript.LoadCode(@"using CSScriptNativeApi;
|
|
||||||
public class Script : ICalc
|
|
||||||
{
|
|
||||||
public int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
if(Host != null)
|
|
||||||
Host.Log(""Sum is invoked"");
|
|
||||||
return a + b;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HostApp Host { get; set; }
|
|
||||||
}")
|
|
||||||
.CreateObject("*");
|
|
||||||
calc.Host = host;
|
|
||||||
int result = calc.Sum(1, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LoadCode_WithDuckTypedInterface(HostApp host)
|
|
||||||
{
|
|
||||||
// 1 - LoadCode compiles code and returns instance of a first class in the compiled assembly
|
|
||||||
// 2- The script class doesn't implement host app interface but it can still be aligned to
|
|
||||||
// one as long at it implements the interface members
|
|
||||||
// 3 - In this sample host object is passed into script routine.
|
|
||||||
|
|
||||||
//This use-case uses Interface Alignment and this requires all assemblies involved to have
|
|
||||||
//non-empty Assembly.Location
|
|
||||||
CSScript.GlobalSettings.InMemoryAssembly = false;
|
|
||||||
|
|
||||||
ICalc calc = CSScript.LoadCode(@"using CSScriptNativeApi;
|
|
||||||
public class Script
|
|
||||||
{
|
|
||||||
public int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
if(Host != null)
|
|
||||||
Host.Log(""Sum is invoked"");
|
|
||||||
return a + b;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HostApp Host { get; set; }
|
|
||||||
}")
|
|
||||||
.CreateObject("*")
|
|
||||||
.AlignToInterface<ICalc>();
|
|
||||||
calc.Host = host;
|
|
||||||
int result = calc.Sum(1, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ExecuteAndUnload()
|
|
||||||
{
|
|
||||||
// The script will be loaded into a temporary AppDomain and unloaded after the execution.
|
|
||||||
|
|
||||||
// Note: remote execution is a subject of some restrictions associated with the nature of the
|
|
||||||
// CLR cross-AppDomain interaction model:
|
|
||||||
// * the script class must be serializable or derived from MarshalByRefObject.
|
|
||||||
//
|
|
||||||
// * any object (call arguments, return objects) that crosses ApPDomain boundaries
|
|
||||||
// must be serializable or derived from MarshalByRefObject.
|
|
||||||
//
|
|
||||||
// * long living script class instances may get disposed in remote domain even if they are
|
|
||||||
// being referenced in the current AppDomain. You need to use the usual .NET techniques
|
|
||||||
// to prevent that. See LifetimeManagement.cs sample for details.
|
|
||||||
|
|
||||||
//This use-case uses Interface Alignment and this requires all assemblies involved to have
|
|
||||||
//non-empty Assembly.Location
|
|
||||||
CSScript.GlobalSettings.InMemoryAssembly = false;
|
|
||||||
|
|
||||||
var code = @"using System;
|
|
||||||
public class Script : MarshalByRefObject
|
|
||||||
{
|
|
||||||
public void Hello(string greeting)
|
|
||||||
{
|
|
||||||
Console.WriteLine(greeting);
|
|
||||||
}
|
|
||||||
}";
|
|
||||||
|
|
||||||
//Note: usage of helper.CreateAndAlignToInterface<IScript>("Script") is also acceptable
|
|
||||||
using (var helper = new AsmHelper(CSScript.CompileCode(code), null, deleteOnExit: true))
|
|
||||||
{
|
|
||||||
IScript script = helper.CreateAndAlignToInterface<IScript>("*");
|
|
||||||
script.Hello("Hi there...");
|
|
||||||
}
|
|
||||||
//from this point AsmHelper is disposed and the temp AppDomain is unloaded
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void DebugTest()
|
|
||||||
{
|
|
||||||
//pops up an assertion dialog
|
|
||||||
dynamic script = CSScript.LoadCode(@"using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
public class Script
|
|
||||||
{
|
|
||||||
public int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
Debug.Assert(false,""Testing CS-Script debugging..."");
|
|
||||||
return a+b;
|
|
||||||
}
|
|
||||||
}", null, debugBuild: true).CreateObject("*");
|
|
||||||
|
|
||||||
int result = script.Sum(1, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Log(string message)
|
|
||||||
{
|
|
||||||
Console.WriteLine(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IScript
|
|
||||||
{
|
|
||||||
void Hello(string greeting);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ICalc
|
|
||||||
{
|
|
||||||
HostApp Host { get; set; }
|
|
||||||
|
|
||||||
int Sum(int a, int b);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Samples
|
|
||||||
{
|
|
||||||
static public void CompilingHistory()
|
|
||||||
{
|
|
||||||
string script = Path.GetTempFileName();
|
|
||||||
string scriptAsm = script + ".dll";
|
|
||||||
CSScript.KeepCompilingHistory = true;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File.WriteAllText(script, @"using System;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
public class Script
|
|
||||||
{
|
|
||||||
public int Sum(int a, int b)
|
|
||||||
{
|
|
||||||
return a+b;
|
|
||||||
}
|
|
||||||
}");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CSScript.CompileFile(script, scriptAsm, false, null);
|
|
||||||
|
|
||||||
CompilingInfo info = CSScript.CompilingHistory
|
|
||||||
.Values
|
|
||||||
.FirstOrDefault(item => item.ScriptFile == script);
|
|
||||||
if (info != null)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Script: " + info.ScriptFile);
|
|
||||||
|
|
||||||
Console.WriteLine("Referenced assemblies:");
|
|
||||||
foreach (string asm in info.Input.ReferencedAssemblies)
|
|
||||||
Console.WriteLine(asm);
|
|
||||||
|
|
||||||
if (info.Result.Errors.HasErrors)
|
|
||||||
{
|
|
||||||
foreach (CompilerError err in info.Result.Errors)
|
|
||||||
if (!err.IsWarning)
|
|
||||||
Console.WriteLine("Error: " + err.ErrorText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CSScript.CompilingHistory.Clear();
|
|
||||||
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
CSScript.KeepCompilingHistory = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -2,8 +2,8 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core.Events;
|
using Artemis.Core.Events;
|
||||||
using Artemis.Core.Models;
|
|
||||||
using Artemis.Plugins.Interfaces;
|
using Artemis.Plugins.Interfaces;
|
||||||
|
using Artemis.Plugins.Models;
|
||||||
|
|
||||||
namespace Artemis.Core.Services.Interfaces
|
namespace Artemis.Core.Services.Interfaces
|
||||||
{
|
{
|
||||||
|
|||||||
@ -6,9 +6,9 @@ using System.Linq;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core.Events;
|
using Artemis.Core.Events;
|
||||||
using Artemis.Core.Exceptions;
|
using Artemis.Core.Exceptions;
|
||||||
using Artemis.Core.Models;
|
|
||||||
using Artemis.Core.Services.Interfaces;
|
using Artemis.Core.Services.Interfaces;
|
||||||
using Artemis.Plugins.Interfaces;
|
using Artemis.Plugins.Interfaces;
|
||||||
|
using Artemis.Plugins.Models;
|
||||||
using CSScriptLibrary;
|
using CSScriptLibrary;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Ninject;
|
using Ninject;
|
||||||
@ -66,7 +66,9 @@ namespace Artemis.Core.Services
|
|||||||
throw new ArtemisPluginException(pluginInfo, "Cannot locate a view model for this plugin.");
|
throw new ArtemisPluginException(pluginInfo, "Cannot locate a view model for this plugin.");
|
||||||
|
|
||||||
// Instantiate the ViewModel with Ninject
|
// Instantiate the ViewModel with Ninject
|
||||||
return (IPluginViewModel) _kernel.Get(vmType);
|
var vm = (IPluginViewModel) _kernel.Get(vmType);
|
||||||
|
vm.PluginInfo = pluginInfo;
|
||||||
|
return vm;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
<package id="RGB.NET.Groups" version="0.0.1.20" targetFramework="net46" />
|
<package id="RGB.NET.Groups" version="0.0.1.20" targetFramework="net46" />
|
||||||
<package id="RGB.NET.Presets" version="0.0.1.20" targetFramework="net46" />
|
<package id="RGB.NET.Presets" version="0.0.1.20" targetFramework="net46" />
|
||||||
<package id="Sanford.Multimedia.Midi" version="6.4.2" targetFramework="net46" />
|
<package id="Sanford.Multimedia.Midi" version="6.4.2" targetFramework="net46" />
|
||||||
|
<package id="Stylet" version="1.1.21" targetFramework="net46" />
|
||||||
<package id="System.AppContext" version="4.3.0" targetFramework="net46" />
|
<package id="System.AppContext" version="4.3.0" targetFramework="net46" />
|
||||||
<package id="System.Collections" version="4.3.0" targetFramework="net46" />
|
<package id="System.Collections" version="4.3.0" targetFramework="net46" />
|
||||||
<package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net46" />
|
<package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net46" />
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
using Artemis.Plugins.Interfaces;
|
using Artemis.Plugins.Interfaces;
|
||||||
|
using Artemis.Plugins.Models;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|
||||||
namespace Artemis.Plugins.Abstract
|
namespace Artemis.Plugins.Abstract
|
||||||
{
|
{
|
||||||
public abstract class PluginViewModel : Screen, IPluginViewModel
|
public abstract class PluginViewModel : Screen, IPluginViewModel
|
||||||
{
|
{
|
||||||
|
public PluginInfo PluginInfo { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -30,6 +30,9 @@
|
|||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Ninject, Version=3.3.4.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL">
|
<Reference Include="Ninject, Version=3.3.4.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Ninject.3.3.4\lib\net45\Ninject.dll</HintPath>
|
<HintPath>..\packages\Ninject.3.3.4\lib\net45\Ninject.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
@ -47,11 +50,13 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Abstract\PluginViewModel.cs" />
|
<Compile Include="Abstract\PluginViewModel.cs" />
|
||||||
|
<Compile Include="Interfaces\IDataModelExpansion.cs" />
|
||||||
<Compile Include="Interfaces\IDevice.cs" />
|
<Compile Include="Interfaces\IDevice.cs" />
|
||||||
<Compile Include="Interfaces\ILayerType.cs" />
|
<Compile Include="Interfaces\ILayerType.cs" />
|
||||||
<Compile Include="Interfaces\IModule.cs" />
|
<Compile Include="Interfaces\IModule.cs" />
|
||||||
<Compile Include="Interfaces\IPlugin.cs" />
|
<Compile Include="Interfaces\IPlugin.cs" />
|
||||||
<Compile Include="Interfaces\IPluginViewModel.cs" />
|
<Compile Include="Interfaces\IPluginViewModel.cs" />
|
||||||
|
<Compile Include="Models\PluginInfo.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
10
src/Artemis.Plugins/Interfaces/IDataModelExpansion.cs
Normal file
10
src/Artemis.Plugins/Interfaces/IDataModelExpansion.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace Artemis.Plugins.Interfaces
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
/// <summary>
|
||||||
|
/// Allows you to expand the application-wide datamodel
|
||||||
|
/// </summary>
|
||||||
|
public interface IDataModelExpansion : IPlugin
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,9 @@
|
|||||||
namespace Artemis.Plugins.Interfaces
|
namespace Artemis.Plugins.Interfaces
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
/// <summary>
|
||||||
|
/// Allows you to implement your own RGB device
|
||||||
|
/// </summary>
|
||||||
public interface IDevice : IPlugin
|
public interface IDevice : IPlugin
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
namespace Artemis.Plugins.Interfaces
|
namespace Artemis.Plugins.Interfaces
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
/// <summary>
|
||||||
|
/// Allows you to create your own layer type
|
||||||
|
/// </summary>
|
||||||
public interface ILayerType : IPlugin
|
public interface ILayerType : IPlugin
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
namespace Artemis.Plugins.Interfaces
|
namespace Artemis.Plugins.Interfaces
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
/// <summary>
|
||||||
|
/// Allows you to add support for new games/applications
|
||||||
|
/// </summary>
|
||||||
public interface IModule : IPlugin
|
public interface IModule : IPlugin
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
using System.Threading.Tasks;
|
namespace Artemis.Plugins.Interfaces
|
||||||
|
|
||||||
namespace Artemis.Plugins.Interfaces
|
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This is the base plugin type, use the other interfaces such as IModule to create plugins
|
||||||
|
/// </summary>
|
||||||
public interface IPlugin
|
public interface IPlugin
|
||||||
{
|
{/// <summary>
|
||||||
/// <summary>
|
|
||||||
/// Called when the plugin is loaded
|
/// Called when the plugin is loaded
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void LoadPlugin();
|
void LoadPlugin();
|
||||||
|
|||||||
@ -1,8 +1,14 @@
|
|||||||
using Stylet;
|
using Artemis.Plugins.Models;
|
||||||
|
using Stylet;
|
||||||
|
|
||||||
namespace Artemis.Plugins.Interfaces
|
namespace Artemis.Plugins.Interfaces
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
/// <summary>
|
||||||
|
/// Allows you to create a view model for a plugin
|
||||||
|
/// </summary>
|
||||||
public interface IPluginViewModel : IScreen
|
public interface IPluginViewModel : IScreen
|
||||||
{
|
{
|
||||||
|
PluginInfo PluginInfo { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
using Artemis.Plugins.Interfaces;
|
using Artemis.Plugins.Interfaces;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Artemis.Core.Models
|
namespace Artemis.Plugins.Models
|
||||||
{
|
{
|
||||||
public class PluginInfo
|
public class PluginInfo
|
||||||
{
|
{
|
||||||
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
|
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net46" />
|
||||||
<package id="Ninject" version="3.3.4" targetFramework="net46" />
|
<package id="Ninject" version="3.3.4" targetFramework="net46" />
|
||||||
<package id="Stylet" version="1.1.21" targetFramework="net46" />
|
<package id="Stylet" version="1.1.21" targetFramework="net46" />
|
||||||
</packages>
|
</packages>
|
||||||
@ -93,6 +93,8 @@
|
|||||||
</ApplicationDefinition>
|
</ApplicationDefinition>
|
||||||
<Compile Include="Bootstrapper.cs" />
|
<Compile Include="Bootstrapper.cs" />
|
||||||
<Compile Include="Ninject\UIModule.cs" />
|
<Compile Include="Ninject\UIModule.cs" />
|
||||||
|
<Compile Include="Services\Interfaces\IArtemisUIService.cs" />
|
||||||
|
<Compile Include="Stylet\ArtemisViewManager.cs" />
|
||||||
<Compile Include="Stylet\NinjectBootstrapper.cs" />
|
<Compile Include="Stylet\NinjectBootstrapper.cs" />
|
||||||
<Compile Include="ViewModels\Interfaces\IHomeViewModel.cs" />
|
<Compile Include="ViewModels\Interfaces\IHomeViewModel.cs" />
|
||||||
<Compile Include="ViewModels\Interfaces\IArtemisViewModel.cs" />
|
<Compile Include="ViewModels\Interfaces\IArtemisViewModel.cs" />
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using Artemis.UI.ViewModels.Interfaces;
|
using Artemis.UI.Services.Interfaces;
|
||||||
|
using Artemis.UI.ViewModels.Interfaces;
|
||||||
using Ninject.Extensions.Conventions;
|
using Ninject.Extensions.Conventions;
|
||||||
using Ninject.Modules;
|
using Ninject.Modules;
|
||||||
|
|
||||||
@ -17,6 +18,16 @@ namespace Artemis.UI.Ninject
|
|||||||
.InheritedFrom<IArtemisViewModel>()
|
.InheritedFrom<IArtemisViewModel>()
|
||||||
.BindAllInterfaces();
|
.BindAllInterfaces();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Bind all UI services as singletons
|
||||||
|
Kernel.Bind(x =>
|
||||||
|
{
|
||||||
|
x.FromThisAssembly()
|
||||||
|
.SelectAllClasses()
|
||||||
|
.InheritedFrom<IArtemisUIService>()
|
||||||
|
.BindAllInterfaces()
|
||||||
|
.Configure(c => c.InSingletonScope());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
8
src/Artemis.UI/Services/Interfaces/IArtemisUIService.cs
Normal file
8
src/Artemis.UI/Services/Interfaces/IArtemisUIService.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Artemis.UI.Services.Interfaces
|
||||||
|
{
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public interface IArtemisUIService
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
46
src/Artemis.UI/Stylet/ArtemisViewManager.cs
Normal file
46
src/Artemis.UI/Stylet/ArtemisViewManager.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Markup;
|
||||||
|
using Artemis.Core.Exceptions;
|
||||||
|
using Artemis.Plugins.Interfaces;
|
||||||
|
using Stylet;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Stylet
|
||||||
|
{
|
||||||
|
public class ArtemisViewManager : ViewManager
|
||||||
|
{
|
||||||
|
public ArtemisViewManager(ViewManagerConfig config) : base(config)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override UIElement CreateViewForModel(object model)
|
||||||
|
{
|
||||||
|
if (model is IPluginViewModel)
|
||||||
|
return CreateViewForPlugin(model);
|
||||||
|
|
||||||
|
return base.CreateViewForModel(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
private UIElement CreateViewForPlugin(object model)
|
||||||
|
{
|
||||||
|
var pluginInfo = ((IPluginViewModel) model).PluginInfo;
|
||||||
|
var viewPath = pluginInfo.Folder + pluginInfo.ViewModel.Replace("ViewModel", "View").Replace(".cs", ".xaml");
|
||||||
|
// There doesn't have to be a view so make sure one exists
|
||||||
|
if (!File.Exists(viewPath))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Compile the view if found, must be done on UI thread sadly
|
||||||
|
object view = null;
|
||||||
|
Execute.OnUIThread(() => view = XamlReader.Parse(File.ReadAllText(viewPath)));
|
||||||
|
var viewType = view.GetType();
|
||||||
|
// Make sure it's a valid UIElement
|
||||||
|
if (viewType.IsAbstract || !typeof(UIElement).IsAssignableFrom(viewType))
|
||||||
|
{
|
||||||
|
var e = new ArtemisPluginException(pluginInfo, $"Found type for view: {viewType.Name}, but it wasn't a class derived from UIElement");
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (UIElement) view;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -31,7 +31,7 @@ namespace Artemis.UI.Stylet
|
|||||||
ViewFactory = GetInstance,
|
ViewFactory = GetInstance,
|
||||||
ViewAssemblies = new List<Assembly> {GetType().Assembly}
|
ViewAssemblies = new List<Assembly> {GetType().Assembly}
|
||||||
};
|
};
|
||||||
kernel.Bind<IViewManager>().ToConstant(new ViewManager(viewManagerConfig));
|
kernel.Bind<IViewManager>().ToConstant(new ArtemisViewManager(viewManagerConfig));
|
||||||
|
|
||||||
kernel.Bind<IWindowManagerConfig>().ToConstant(this).InTransientScope();
|
kernel.Bind<IWindowManagerConfig>().ToConstant(this).InTransientScope();
|
||||||
kernel.Bind<IWindowManager>().ToMethod(c => new WindowManager(c.Kernel.Get<IViewManager>(),
|
kernel.Bind<IWindowManager>().ToMethod(c => new WindowManager(c.Kernel.Get<IViewManager>(),
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Artemis.Core.Services.Interfaces;
|
|
||||||
using Artemis.UI.ViewModels.Interfaces;
|
using Artemis.UI.ViewModels.Interfaces;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|
||||||
@ -8,15 +7,6 @@ namespace Artemis.UI.ViewModels
|
|||||||
{
|
{
|
||||||
public class HomeViewModel : Screen, IHomeViewModel
|
public class HomeViewModel : Screen, IHomeViewModel
|
||||||
{
|
{
|
||||||
private readonly IPluginService _pluginService;
|
|
||||||
|
|
||||||
public HomeViewModel(IPluginService pluginService)
|
|
||||||
{
|
|
||||||
_pluginService = pluginService;
|
|
||||||
|
|
||||||
_pluginService.FinishedLoadedPlugins += PluginServiceOnFinishedLoadedPlugins;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Title => "Home";
|
public string Title => "Home";
|
||||||
|
|
||||||
public void OpenUrl(string url)
|
public void OpenUrl(string url)
|
||||||
@ -25,15 +15,5 @@ namespace Artemis.UI.ViewModels
|
|||||||
if (Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute))
|
if (Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute))
|
||||||
Process.Start(url);
|
Process.Start(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Populates the sidebar with plugins when they are finished loading
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender"></param>
|
|
||||||
/// <param name="eventArgs"></param>
|
|
||||||
private void PluginServiceOnFinishedLoadedPlugins(object sender, EventArgs eventArgs)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,6 +1,8 @@
|
|||||||
namespace Artemis.UI.ViewModels.Interfaces
|
using Stylet;
|
||||||
|
|
||||||
|
namespace Artemis.UI.ViewModels.Interfaces
|
||||||
{
|
{
|
||||||
public interface IArtemisViewModel
|
public interface IArtemisViewModel : IScreen
|
||||||
{
|
{
|
||||||
string Title { get; }
|
string Title { get; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,24 +1,57 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Artemis.Core.Services.Interfaces;
|
||||||
|
using Artemis.Plugins.Interfaces;
|
||||||
|
using Artemis.Plugins.Models;
|
||||||
|
using Artemis.UI.Services.Interfaces;
|
||||||
using Artemis.UI.ViewModels.Interfaces;
|
using Artemis.UI.ViewModels.Interfaces;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|
||||||
namespace Artemis.UI.ViewModels
|
namespace Artemis.UI.ViewModels
|
||||||
{
|
{
|
||||||
public class RootViewModel : Conductor<IArtemisViewModel>.Collection.OneActive
|
public class RootViewModel : Conductor<IScreen>.Collection.OneActive
|
||||||
{
|
{
|
||||||
private readonly ICollection<IArtemisViewModel> _artemisViewModels;
|
private readonly ICollection<IArtemisViewModel> _artemisViewModels;
|
||||||
|
private readonly IPluginService _pluginService;
|
||||||
|
|
||||||
public RootViewModel(ICollection<IArtemisViewModel> artemisViewModels)
|
public RootViewModel(ICollection<IArtemisViewModel> artemisViewModels, IPluginService pluginService)
|
||||||
{
|
{
|
||||||
_artemisViewModels = artemisViewModels;
|
_artemisViewModels = artemisViewModels;
|
||||||
|
_pluginService = pluginService;
|
||||||
|
|
||||||
// Add the built-in items
|
// Add the built-in items
|
||||||
Items.AddRange(artemisViewModels);
|
Items.AddRange(artemisViewModels);
|
||||||
// Activate the home item
|
// Activate the home item
|
||||||
ActiveItem = _artemisViewModels.First(v => v.GetType() == typeof(HomeViewModel));
|
ActiveItem = _artemisViewModels.First(v => v.GetType() == typeof(HomeViewModel));
|
||||||
|
|
||||||
|
// Sync up with the plugin service
|
||||||
|
Modules = new BindableCollection<PluginInfo>();
|
||||||
|
LoadingPlugins = _pluginService.LoadingPlugins;
|
||||||
|
_pluginService.StartedLoadingPlugins += PluginServiceOnStartedLoadingPlugins;
|
||||||
|
_pluginService.FinishedLoadedPlugins += PluginServiceOnFinishedLoadedPlugins;
|
||||||
|
|
||||||
|
if (!LoadingPlugins)
|
||||||
|
Modules.AddRange(_pluginService.Plugins.Where(p => p.Plugin is IModule));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IObservableCollection<PluginInfo> Modules { get; set; }
|
||||||
|
|
||||||
public bool MenuOpen { get; set; }
|
public bool MenuOpen { get; set; }
|
||||||
|
public bool LoadingPlugins { get; set; }
|
||||||
|
|
||||||
|
private void PluginServiceOnStartedLoadingPlugins(object sender, EventArgs eventArgs)
|
||||||
|
{
|
||||||
|
LoadingPlugins = true;
|
||||||
|
Modules.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PluginServiceOnFinishedLoadedPlugins(object sender, EventArgs eventArgs)
|
||||||
|
{
|
||||||
|
LoadingPlugins = false;
|
||||||
|
Modules.AddRange(_pluginService.Plugins.Where(p => p.Plugin is IModule));
|
||||||
|
NavigateToModule(Modules.First());
|
||||||
|
}
|
||||||
|
|
||||||
public void NavigateToHome()
|
public void NavigateToHome()
|
||||||
{
|
{
|
||||||
@ -39,5 +72,13 @@ namespace Artemis.UI.ViewModels
|
|||||||
ActivateItem(_artemisViewModels.First(v => v.GetType() == typeof(SettingsViewModel)));
|
ActivateItem(_artemisViewModels.First(v => v.GetType() == typeof(SettingsViewModel)));
|
||||||
MenuOpen = false;
|
MenuOpen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async void NavigateToModule(PluginInfo pluginInfo)
|
||||||
|
{
|
||||||
|
// Create a view model for the given plugin info (which will be a module)
|
||||||
|
var viewModel = await _pluginService.GetPluginViewModel(pluginInfo);
|
||||||
|
// Tell Stylet to active the view model, the view manager will compile and show the XAML
|
||||||
|
ActivateItem(viewModel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user