对此进行后续跟进很好的答案,我想知道 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();
}
是的,你可以这样做,而且效果很好。然而,虽然使用动态关键字更方便,但它利用了后期绑定,并且在这个意义上仍然与显式使用反射一样不安全。如果您的设计允许,最好使用共享接口或基类进行早期绑定。为此,您可以在程序集中或第三个共享程序集中创建公共类型,然后从正在动态编译的新程序集添加对该程序集的引用。然后,在生成的代码中,您可以从引用的程序集中的共享类型继承。例如,创建一个接口:
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();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)