我真的想在运行时生成一个新类型。基本上,我想创建看起来像这样的类型:
public class MySpecial123
{
public Func<int, DateTime, int> salesVectorCalc; // field
public int CallSalesVectorCalculation(int i, DateTime d)
(
return salesVectorCalc(i, d);
)
}
某些类型会因用户/数据库输入而异,所以我无法以其他任何方式完成它,然后在运行时创建类型。还有更复杂的问题,但我想让我的问题变得简单,所以我只是在这里提出基本问题。我需要做更多代,就像你在这里看到的那样。
我认为使用Reflection.Emit
会很酷,但后来我意识到生成代码并在内存中编译可能更容易。有谁知道哪个更好?我真的想看看如何做其中任何一个的例子。
答案 0 :(得分:5)
当您说“在运行时生成类型”时,听起来好像您要求动态输入。
在C#4.0中,只需使用动态关键字即可完成。
但是,您还描述了类似于代码生成的东西 - 如果这更像您所追求的,为什么不使用类似T4模板的东西在“预编译”阶段生成您的类型?
答案 1 :(得分:2)
将代码生成为字符串然后将其动态编译为内存中的程序集非常容易。然后,您可以通过以下方式调用方法并访问字段:
代码:
public static Assembly Compile(string source)
{
var codeProvider = new CSharpCodeProvider(new Dictionary<String, String> { { "CompilerVersion", "v4.0" } });
var compilerParameters = new CompilerParameters();
compilerParameters.ReferencedAssemblies.Add("System.dll");
compilerParameters.ReferencedAssemblies.Add("System.Core.dll");
compilerParameters.ReferencedAssemblies.Add("System.Xml.dll");
compilerParameters.ReferencedAssemblies.Add("System.Xml.Linq.dll");
compilerParameters.CompilerOptions = "/t:library";
compilerParameters.GenerateInMemory = true;
var result = codeProvider.CompileAssemblyFromSource(compilerParameters, source);
if (result.Errors.Count > 0)
{
foreach (CompilerError error in result.Errors)
{
Debug.WriteLine("ERROR Line {0:000}: {1}", error.Line, error.ErrorText);
}
return null;
}
else
{
return result.CompiledAssembly;
}
}