Roslyn, how can I instantiate a class in a script at runtime and call the methods of this class?

I understand how I can execute entire scripts using Roslyn in C #, but now I want to compile the class inside the script, instantiate it, parse it using the interface, and then call the methods that compiled and created the class.

Does Roslin reveal such functionality? Can you please point me to this approach?

thank

+4
source share
1 answer

I think you can do what you want, like so:

namespace ConsoleApp2 {
    class Program {
        static void Main(string[] args) {
            // create class and return its type from script
            // reference current assembly to use interface defined below
            var script = CSharpScript.Create(@"
        public class Test : ConsoleApp2.IRunnable {
            public void Run() {
                System.Console.WriteLine(""test"");
            }
        }
        return typeof(Test);
        ", ScriptOptions.Default.WithReferences(Assembly.GetExecutingAssembly()));
            script.Compile();
            // run and you get Type object for your fresh type
            var testType = (Type) script.RunAsync().Result.ReturnValue;
            // create and cast to interface
            var runnable = (IRunnable)Activator.CreateInstance(testType);
            // use
            runnable.Run();
            Console.ReadKey();
        }
    }

    public interface IRunnable {
        void Run();
    }
}

Instead of returning a type created with a script, you can also use global variables and return it this way:

namespace ConsoleApp2 {
    class Program {
        static void Main(string[] args) {

            var script = CSharpScript.Create(@"
        public class Test : ConsoleApp2.IRunnable {
            public void Run() {
                System.Console.WriteLine(""test"");
            }
        }
        MyTypes.Add(typeof(Test).Name, typeof(Test));
        ", ScriptOptions.Default.WithReferences(Assembly.GetExecutingAssembly()), globalsType: typeof(ScriptGlobals));
            script.Compile();
            var globals = new ScriptGlobals();
            script.RunAsync(globals).Wait();            
            var runnable = (IRunnable)Activator.CreateInstance(globals.MyTypes["Test"]);
            runnable.Run();
            Console.ReadKey();
        }
    }

    public class ScriptGlobals {
        public Dictionary<string, Type> MyTypes { get; } = new Dictionary<string, Type>();
    }

    public interface IRunnable {
        void Run();
    }
}

.

, script? , script.Compile() GAC? ? Activator.CreateInstance(typeofClass), script

gac - ​​ , , Assembly.Load(someByteArray). , , Compile, , RunAsunc(). , , : β„›*fde34898-86d2-42e9-a786-e3c1e1befa78#1-0. , , , :

script.Compile();
var asmAfterCompile = AppDomain.CurrentDomain.GetAssemblies().Single(c =>
     String.IsNullOrWhiteSpace(c.Location) && c.CodeBase.EndsWith("Microsoft.CodeAnalysis.Scripting.dll"));

, , ( script ), , . - ( , ).

, - . script wrapping. " β„– 0", , . , Test script. , " β„– 0 + ". , , :

var testType = asmAfterCompile.GetTypes().Single(c => c.Name == "Test");

, - .

, :

script.Compile();
var stream = new MemoryStream();
var emitResult = script.GetCompilation().Emit(stream);
if (emitResult.Success) {
    var asm = Assembly.Load(stream.ToArray());
}

, .

+4

Source: https://habr.com/ru/post/1689045/


All Articles