如何在 C# 中生成新类型

发布于 2024-11-05 02:13:24 字数 489 浏览 0 评论 0原文

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

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

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

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

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

I really want to generate a new type at runtime. Essentially, I want to create types that look something like this:

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

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

Some of the types will vary based on user/DB inputs, so I can't really accomplish it any other way then to create the type at runtime. There is also more complexity, but I wanted to make my question simple so I am only asking the essential questions here. I will need to do more generation that just what you see here.

I was thinking it would be cool to use Reflection.Emit, but then I realized it might be easier to generate the code and compile all in memory. Does anyone know which is better? I would really like to see an example of how to do either one of these.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

满天都是小星星 2024-11-12 02:13:24

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

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

但是,您还描述了类似于代码生成的内容 - 如果这更符合您的需求,为什么不使用 T4 模板之类的内容在“预编译”阶段生成类型呢?

When you say "generate a type at runtime" it sounds as though you are asking for dynamic typing.

In C# 4.0 it's done simply with the dynamic keyword.

However, you also describe something akin to code generation - if this is more what you are after, why not use something like T4 Templates to generate your types in a "pre-compile" phase?

夏日落 2024-11-12 02:13:24

将代码生成为字符串,然后将其动态编译为内存中的程序集非常容易。然后,您可以通过以下任一方式调用您的方法并访问您的字段:

  • 使用反射
  • 使用dynamic关键字
  • 转换为接口/基类(如果您的新类继承自其中一个)

代码:

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

It is pretty easy to generate your code as a string and then dynamically compile it to an in-memory assembly. You can then call your methods and access your fields by either:

  • Using reflection
  • Using the dynamic keyword
  • Casting to an interface / base class (if your new class inherits from one)

Code:

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;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文