使用DLR运行与CompileAssemblyFromSource生成的代码?(Use DLR to

2019-06-25 06:07发布

在此跟进出色答卷 ,我想知道如果使用DLR的dynamic关键字可以允许生成的汇编编写代码的更简洁的方式。

例如,可以将上述答案的代码:

using (Microsoft.CSharp.CSharpCodeProvider foo = 
           new Microsoft.CSharp.CSharpCodeProvider())
{
    var res = foo.CompileAssemblyFromSource(
        new System.CodeDom.Compiler.CompilerParameters() {  
            GenerateInMemory = true 
        }, 
        "public class FooClass { public string Execute() { return \"output!\";}}"
    );

    var type = res.CompiledAssembly.GetType("FooClass");
    var obj = Activator.CreateInstance(type);
    var output = type.GetMethod("Execute").Invoke(obj, new object[] { });
}

成为类似:

using (Microsoft.CSharp.CSharpCodeProvider foo = 
           new Microsoft.CSharp.CSharpCodeProvider())
{
    var res = foo.CompileAssemblyFromSource(
        new System.CodeDom.Compiler.CompilerParameters() {  
            GenerateInMemory = true 
        }, 
        "public class FooClass { public string Execute() { return \"output!\";}}"
    );

    var type = res.CompiledAssembly.GetType("FooClass");
    dynamic obj = Activator.CreateDynamicInstance(type);
    var output = obj.Execute();
}

Answer 1:

是的,你可以做到这一点,它工作得很好。 然而,在使用动态关键字更方便,它利用后期绑定,仍然是一样不安全的,在这个意义上,作为明确使用反射。 如果您的设计允许的话,那就更好了使用共享接口或基类早期绑定。 您可以通过在组装或在第三,共享程序集创建一个公开的类型做到这一点,然后从一个新的你正在编译动态向组装添加引用。 然后,在所生成的代码,可以从在参考组件共享类型继承。 例如,创建一个接口:

public interface IFoo
{
    string Execute();
}

然后动态编译这样的组件:

using (Microsoft.CSharp.CSharpCodeProvider foo = new Microsoft.CSharp.CSharpCodeProvider())
{
    var params = new System.CodeDom.Compiler.CompilerParameters();
    params.GenerateInMemory = true;

    // Add the reference to the current assembly which defines IFoo
    params.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);

    // Implement the IFoo interface in the dynamic code
    var res = foo.CompileAssemblyFromSource(params, "public class FooClass : IFoo { public string Execute() { return \"output!\";}}");
    var type = res.CompiledAssembly.GetType("FooClass");

    // Cast the created object to IFoo
    IFoo obj = (IFoo)Activator.CreateInstance(type);

    // Use the object through the IFoo interface
    obj.Execute();
}

这取决于你如何的控制力动态代码,这可能会或可能不会是可能的,但是当它是,它很高兴有编译时类型检查。 例如,如果你试图执行:

IFoo obj = (IFoo)Activator.CreateInstance(type);
obj.Execcute();

这第二条线会立即编译失败,因为它是拼写错误,而使用动态关键字或反射,该行会成功编译但它会导致运行时异常。 例如,下面不会得到一个编译时错误:

dynamic obj = Activator.CreateDynamicInstance(type);
obj.Execcute();


Answer 2:

这就是DLR设计的方案之一。 你可以用这种方式来调用动态加载的类的成员,同时避免从手动调用所有的额外打字.GetMethod().Invoke()



文章来源: Use DLR to run code generated with CompileAssemblyFromSource?