mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-12 03:48:56 +00:00
Further expanded plugins
Added navigation between modules
This commit is contained in:
1 parent
7773d377a2
commit
6a8edfc00a
21 files changed
+1193
-163
No files matched your search
@@ -0,0 +1,295 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user