0

我真的很想在运行时生成一个新类型。本质上,我想创建看起来像这样的类型:

public class MySpecial123
{
    public Func<int, DateTime, int> salesVectorCalc; // field

    public int CallSalesVectorCalculation(int i, DateTime d)
    (
        return salesVectorCalc(i, d);
    )
}

某些类型会根据用户/数据库输入而有所不同,因此除了在运行时创建类型之外,我无法真正完成它。还有更多的复杂性,但我想让我的问题简单,所以我在这里只问基本问题。我需要做更多的一代,就像你在这里看到的那样。

我认为使用它会很酷Reflection.Emit,但后来我意识到生成代码并在内存中编译可能更容易。有谁知道哪个更好?我真的很想看到一个如何做其中任何一个的例子。

4

2 回答 2

5

当您说“在运行时生成类型”时,听起来好像您在要求动态类型

在 C# 4.0 中,只需使用 dynamic 关键字即可。

但是,您还描述了类似于代码生成的东西——如果这更像是您所追求的,为什么不在“预编译”阶段使用诸如 T4 模板之类的东西来生成您的类型呢?

于 2011-05-03T23:50:56.807 回答
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;
    }
}
于 2011-05-04T00:32:18.503 回答