首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用DLR来运行用CompileAssemblyFromSource生成的代码?

使用DLR来运行用CompileAssemblyFromSource生成的代码?
EN

Stack Overflow用户
提问于 2012-06-06 20:45:09
回答 2查看 1.8K关注 0票数 5

在这个excellent answer之后,我想知道使用dynamic关键字的DLR是否允许以一种不太冗长的方式为生成的程序集编写代码。

例如,前面提到的答案的代码:

代码语言:javascript
复制
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[] { });
}

变得像这样:

代码语言:javascript
复制
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();
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-06 21:26:24

是的,你可以这样做,而且效果很好。然而,虽然使用dynamic关键字更方便,但它利用了后期绑定,在这种意义上,它仍然与显式使用反射一样不安全。如果您的设计允许,使用共享接口或基类进行早期绑定甚至更好。为此,可以在程序集中或第三个共享程序集中创建公共类型,然后从动态编译的新程序集中添加对该程序集的引用。然后,在生成的代码中,可以从引用的程序集中的该共享类型继承。例如,创建一个接口:

代码语言:javascript
复制
public interface IFoo
{
    string Execute();
}

然后动态编译程序集,如下所示:

代码语言:javascript
复制
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();
}

这取决于您对动态代码的控制程度,这可能是可能的,也可能是不可能的,但当它实现时,拥有编译时类型检查是很好的。例如,如果您尝试执行以下命令:

代码语言:javascript
复制
IFoo obj = (IFoo)Activator.CreateInstance(type);
obj.Execcute();

第二行将立即无法编译,因为它拼写错误,而使用dynamic关键字或反射,该行将成功编译,但它将导致运行时异常。例如,下面的代码不会出现编译时错误:

代码语言:javascript
复制
dynamic obj = Activator.CreateDynamicInstance(type);
obj.Execcute();
票数 7
EN

Stack Overflow用户

发布于 2012-06-06 20:52:11

这是DLR设计的场景之一。您可以使用它来调用动态加载类型的成员,同时避免手动调用.GetMethod().Invoke()的所有额外类型。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10914484

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档