/// <summary> /// Wraps C# code fragment into auto-generated class (type name <c>DynamicClass</c>), evaluates it and loads /// the class to the current AppDomain. /// <para>Returns instance of <c>T</c> delegate for the first method in the auto-generated class.</para> /// </summary> /// <example> /// <code> /// var Product = CSScript.RoslynEvaluator /// .LoadDelegate<Func<int, int, int>>( /// @"int Product(int a, int b) /// { /// return a * b; /// }"); /// /// int result = Product(3, 2); /// </code> /// </example> /// <param name="code">The C# code.</param> /// <returns>Instance of <c>T</c> delegate.</returns> public T LoadDelegate<T>(string code) where T : class { string scriptText = CSScript.WrapMethodToAutoClass(code, true, false); Assembly asm = CompileCode(scriptText); var method = asm.GetTypes().First(t => t.Name == "DynamicClass").GetMethods().First(); return System.Delegate.CreateDelegate(typeof(T), method) as T; }
/// <summary> /// Wraps C# code fragment into auto-generated class (type name <c>DynamicClass</c>), evaluates it and loads the class to the current AppDomain. /// <para>Returns typed <see cref="CSScriptLibrary.MethodDelegate{T}"/> for class-less style of invoking.</para> /// </summary> /// <typeparam name="T">The delegate return type.</typeparam> /// <example> /// <code> /// var product = CSScript.RoslynEvaluator /// .CreateDelegate<int>(@"int Product(int a, int b) /// { /// return a * b; /// }"); /// /// int result = product(3, 2); /// </code> /// </example> /// <param name="code">The C# code.</param> /// <returns> The instance of a typed <see cref="CSScriptLibrary.MethodDelegate{T}"/></returns> public MethodDelegate <T> CreateDelegate <T>(string code) { string scriptText = CSScript.WrapMethodToAutoClass(code, true, false); var asm = CompileCode(scriptText); var method = asm.GetTypes() .Where(x => x.GetName().EndsWith("DynamicClass")) .SelectMany(x => x.GetMethods()) .FirstOrDefault(); T invoker(params object[] args) { return((T)method.Invoke(null, args)); } return(invoker); }
/// <summary> /// Wraps C# code fragment into auto-generated class (type name <c>DynamicClass</c>), evaluates it and loads /// the class to the current AppDomain. /// <para> /// After initializing the class instance it is aligned to the interface specified by the parameter <c>T</c>. /// </para> /// </summary> /// <example>The following is the simple example of the interface alignment: /// <code> /// public interface ICalc /// { /// int Sum(int a, int b); /// int Div(int a, int b); /// } /// .... /// ICalc script = CSScript.CodeDomEvaluator /// .LoadMethod<ICalc>(@"public int Sum(int a, int b) /// { /// return a + b; /// } /// public int Div(int a, int b) /// { /// return a/b; /// }"); /// int result = script.Div(15, 3); /// </code> /// </example> /// <typeparam name="T">The type of the interface type the script class instance should be aligned to.</typeparam> /// <param name="code">The C# script text.</param> /// <returns>Aligned to the <c>T</c> interface instance of the auto-generated class defined in the script.</returns> public T LoadMethod <T>(string code) where T : class { string scriptText = CSScript.WrapMethodToAutoClass(code, false, false); return(LoadCode <T>(scriptText)); }
/// <summary> /// Wraps C# code fragment into auto-generated class (type name <c>DynamicClass</c>), evaluates it and loads /// the class to the current AppDomain. /// </summary> /// <example>The following is the simple example of the LoadMethod usage: /// <code> /// dynamic script = CSScript.CodeDomEvaluator /// .LoadMethod(@"int Product(int a, int b) /// { /// return a * b; /// }"); /// /// int result = script.Product(3, 2); /// </code> /// </example> /// <param name="code">The C# script text.</param> /// <returns>Instance of the first class defined in the script.</returns> public object LoadMethod(string code) { string scriptText = CSScript.WrapMethodToAutoClass(code, false, false); return(LoadCode(scriptText)); }
/// <summary> /// Wraps C# code fragment into auto-generated class (type name <c>DynamicClass</c>), evaluates it and loads the class to the current AppDomain. /// <para>Returns typed <see cref="CSScriptLibrary.MethodDelegate{T}"/> for class-less style of invoking.</para> /// </summary> /// <typeparam name="T">The delegate return type.</typeparam> /// <example> /// <code> /// var product = CSScript.CodeDomEvaluator /// .CreateDelegate<int>(@"int Product(int a, int b) /// { /// return a * b; /// }"); /// /// int result = product(3, 2); /// </code> /// </example> /// <param name="code">The C# code.</param> /// <returns> The instance of a typed <see cref="CSScriptLibrary.MethodDelegate{T}"/></returns> public MethodDelegate <T> CreateDelegate <T>(string code) { string scriptText = CSScript.WrapMethodToAutoClass(code, true, false); return(CompileCode(scriptText).GetStaticMethod <T>()); }
/// <summary> /// Wraps C# code fragment into auto-generated class (type name <c>DynamicClass</c>) and evaluates it. /// <para> /// This method is a logical equivalent of <see cref="CSScriptLibrary.IEvaluator.CompileCode"/> but is allows you to define /// your script class by specifying class method instead of whole class declaration.</para> /// </summary> /// <example> ///<code> /// dynamic script = CSScript.CodeDomEvaluator /// .CompileMethod(@"int Sum(int a, int b) /// { /// return a+b; /// }") /// .CreateObject("*"); /// /// var result = script.Sum(7, 3); /// </code> /// </example> /// <param name="code">The C# code.</param> /// <returns>The compiled assembly.</returns> public Assembly CompileMethod(string code) { string scriptText = CSScript.WrapMethodToAutoClass(code, false, false); return(CompileCode(scriptText)); }
/// <summary> /// Wraps C# code fragment into auto-generated class (type name <c>DynamicClass</c>), /// evaluates it and loads the class to the remote AppDomain. /// <para>Returns non-typed <see cref="CSScriptLibrary.MethodDelegate"/> of the remote object for /// class-less style of invoking.</para> /// </summary> /// <example> /// <code> /// /// var log = CSScript.Evaluator /// .CreateDelegateRemotely( /// @"void Log(string message) /// { /// Console.WriteLine(message); /// }"); /// /// log("Test message"); /// /// log.UnloadOwnerDomain(); /// </code> /// </example> /// <param name="evaluator">The evaluator.</param> /// <param name="code">The C# code.</param> /// <param name="probingDirs">The probing directories for the assemblies the script /// assembly depends on.</param> /// <returns> The instance of a 'duck typed' <see cref="CSScriptLibrary.MethodDelegate"/></returns> public static MethodDelegate CreateDelegateRemotely(this IEvaluator evaluator, string code, params string[] probingDirs) { string scriptCode = CSScript.WrapMethodToAutoClass(code, true, false, "MarshalByRefObject"); var agentDef = @" public class RemoteAgent : MarshalByRefObject, CSScriptLibrary.IRemoteAgent { public object Method(params object[] parameters) { return Implementation(parameters); } public CSScriptLibrary.MethodDelegate Implementation {get; set;} }"; var cx = RemoteLoadingContext.NewFor(evaluator, scriptCode + agentDef); var remoteDomain = evaluator.GetRemoteDomain(); if (remoteDomain == null) { remoteDomain = AppDomain.CurrentDomain.Clone(); } remoteDomain.Execute(context => { try { IEvaluator eval = RemoteLoadingContext.CreateEvaluator(context); var script = eval.ReferenceAssemblyOf <CSScript>() .CompileCode(context.code); //var asm = script.GetType().Assembly.Location; #if net45 string agentTypeName = script.DefinedTypes.Where(t => t.Name == "RemoteAgent").First().FullName; #else string agentTypeName = script.GetModules() .SelectMany(m => m.GetTypes()) .Where(t => t.Name == "RemoteAgent") .First() .FullName; #endif var agent = (IRemoteAgent)script.CreateObject(agentTypeName); agent.Implementation = script.GetStaticMethod(); context.scriptObj = agent; } catch (Exception e) { context.error = e.ToString(); } }, cx, probingDirs); if (cx.error != null) { throw new CompilerException("Exception in the remote AppDomain: " + cx.error); } var agentProxy = (IRemoteAgent)cx.scriptObj; MethodDelegate result = (param) => agentProxy.Method(param); evaluator.SetRemoteDomain(remoteDomain); result.SetOwnerDomain(remoteDomain) .SetOwnerObject(agentProxy); return(result); }
/// <summary> /// Loads the method remotely. /// LoadMethodRemotely is essentially the same as <see cref="CSScriptLibrary.EvaluatorRemoting.LoadCodeRemotely{T}"/>. /// It just deals not with the whole class definition but a method(s) only. And the rest of the class definition is /// added automatically by CS-Script. /// </summary> /// <example> ///<code> /// var script = CSScript.Evaluator /// .LoadMethodRemotely<ICalc>( /// @"public int Sum(int a, int b) /// { /// return a+b; /// } /// public int Sub(int a, int b) /// { /// return a-b; /// }"); /// /// int result = script.Sum(15, 3)); /// /// // after the next line call the remote domain with loaded script will be unloaded /// script.UnloadOwnerDomain(); /// </code> /// </example> /// <typeparam name="T">The type of the T.</typeparam> /// <param name="evaluator">The evaluator.</param> /// <param name="code">The code.</param> /// <returns></returns> public static T LoadMethodRemotely <T>(this IEvaluator evaluator, string code) where T : class { string scriptCode = CSScript.WrapMethodToAutoClass(code, false, false, "MarshalByRefObject, " + typeof(T)); return(evaluator.LoadCodeRemotely <T>(scriptCode)); }