使用DLR运行code与CompileAssemblyFromSource产生的? [英] Use DLR to run code generated with CompileAssemblyFromSource?

查看:288
本文介绍了使用DLR运行code与CompileAssemblyFromSource产生的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在此<一个跟进href="http://stackoverflow.com/questions/3188882/compile-and-run-dynamic-$c$c-without-generating-exe/3188953#3188953">excellent回答,我想知道,如果使用动态DLR 关键字可以允许写$ C $下生成的程序集一个更简洁的方式。

例如,可以将上述答案是code:

 使用(Microsoft.CSharp.CSharp codeProvider富=
           新Microsoft.CSharp.CSharp codeProvider())
{
    VAR解析度= foo.CompileAssemblyFromSource(
        新的系统。codeDom.Compiler.CompilerParameters(){
            GenerateInMemory =真
        },
        公共类FooClass {公共字符串执行(){返回\输出\!;}}
    );

    VAR类型= res.CompiledAssembly.GetType(FooClass);
    变种物镜= Activator.CreateInstance(类型);
    无功输出= type.GetMethod(执行)调用(OBJ,新的对象[] {})。
}
 

变成是这样的:

 使用(Microsoft.CSharp.CSharp codeProvider富=
           新Microsoft.CSharp.CSharp codeProvider())
{
    VAR解析度= foo.CompileAssemblyFromSource(
        新的系统。codeDom.Compiler.CompilerParameters(){
            GenerateInMemory =真
        },
        公共类FooClass {公共字符串执行(){返回\输出\!;}}
    );

    VAR类型= res.CompiledAssembly.GetType(FooClass);
    动态物镜= Activator.CreateDynamicInstance(类型);
    无功输出= obj.Execute();
}
 

解决方案

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

 公共接口的IFoo
{
    串执行();
}
 

然后动态编译的程序集是这样的:

 使用(Microsoft.CSharp.CSharp codeProvider富=新Microsoft.CSharp.CSharp codeProvider())
{
    VAR PARAMS =新系统codeDom.Compiler.CompilerParameters()。
    params.GenerateInMemory = TRUE;

    //添加引用到当前的组件,其定义的IFoo
    params.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly()位置。);

    //实现在动态code中的IFoo的接口
    VAR解析度= foo.CompileAssemblyFromSource(PARAMS,公共类FooClass:的​​IFoo {公共字符串执行(){返回\的输出\;}!});
    VAR类型= res.CompiledAssembly.GetType(FooClass);

    创建的对象//强制转换为IFoo的
    IFoo的OBJ =(的IFoo)Activator.CreateInstance(类型);

    //通过IFoo的接口使用对象
    obj.Execute();
}
 

根据您的控制力动态code,这可能会或可能不会是可能的,但是当它是,它很高兴有编译时类型检查。例如,如果你试图执行:

  IFoo的OBJ =(的IFoo)Activator.CreateInstance(类型);
obj.Execcute();
 

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

 动态OBJ = Activator.CreateDynamicInstance(类型);
obj.Execcute();
 

Following up on this excellent answer, I'm wondering if the DLR using the dynamic keyword can allow a less verbose way of writing code for the generated assembly.

For example, can the aforementioned answer's code:

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[] { });
}

become something like:

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();
}

解决方案

Yes, you can do that and it works well. However, while using the dynamic keyword is more convenient, it utilizes late-binding and is still just as unsafe, in that sense, as explicitly using reflection. If your design allows it, it is even better to use a shared interface or base class for early-binding. You can do this by creating a public type in your assembly or in a third, shared assembly, and then add a reference to that assembly from the new one you are dynamically compiling. Then, in the generated code, you can inherit from that shared type in the referenced assembly. For instance, create an interface:

public interface IFoo
{
    string Execute();
}

Then dynamically compile the assembly like this:

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();
}

Depending on how much control you have over the dynamic code, this may or may not be possible, but when it is, it's nice to have the compile-time type-checking. For instance, if you tried to execute:

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

That second line would immediately fail to compile because it's spelled wrong, whereas with the dynamic keyword or reflection, that line would successfully compile but it would cause a run-time exception. For instance, the following will not get a compile-time error:

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

这篇关于使用DLR运行code与CompileAssemblyFromSource产生的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆