什么是动态生成code。在.NET 4.5中最简单的方法? [英] What's the easiest way to generate code dynamically in .NET 4.5?

查看:175
本文介绍了什么是动态生成code。在.NET 4.5中最简单的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个特定种类的对象映射器的。基本上,我想从数据表具有字段 A B C 的对象,具有属性 A B C (类对象将可以手写)。会有很多不同的数据表和许多不同的类,他们将需要映射到,所以我想做出一个执行此数据复制一个通用的机制。基本上,我想下面的功能:

I'm writing a specific kind of object-mapper. Basically I want to convert from a DataTable that has the fields a, b and c to an object that has properties a, b and c (the class of the object will be written by hand). There will be many different DataTables and many different classes that they will need to map to, so I want to make a generic mechanism that performs this data copying. Basically, I want the following function:

public T Map<T>(DataTable t) where T: new() { ... }

现在,我能做到这一点与反思,但这是缓慢的。该功能将在框架的核心和将被经常使用。所以我想动态code一代。第一次这个方法是运行在一个特定的 T 将进行必要的反思,放出做所有适当的映射匿名方法。下一次它只是运行code。这应该是作为高性能越好。

Now, I can do this with Reflection, but that's slow. This function will be at the core of the framework and will be used often. So I'm thinking about dynamic code generation. The first time this method is run on a specific T it will perform the necessary reflection and emit an anonymous method that does all the appropriate mapping. The next time it will just run that code. This should be as performant as possible.

只是一个问题 - 我从来没有发出code运行时。我怎么做?我看着防爆pressions ,但他们只能做,好了,前pressions,而不是一系列的语句。

Just one problem - I've never emitted code at runtime. How do I do that? I looked at Expressions, but they can only do, well, expressions, not a series of statements.

再有就是codeDOM和 CSHARP codeProvider 。这一类的作品 - 我可以生成C#code为一个字符串,在即时编译它,然后得到一个参考。然而,它涉及到C#编译器,生成一个全新的内存组件。听起来有点...重量级的一个简单的方法。

Then there's CodeDOM and CSharpCodeProvider. That sort of works - I can generate C# code as a string, compile it on-the-fly and then get a reference. However it involves the C# compiler and generates a whole new in-memory assembly. Sounds a bit... heavyweight for one simple method.

有没有一些简单的方法?东西产生一个轻量级的,匿名方法不依附于任何组件(或连接到现有的组件)?

Is there some simpler way? Something that generates a lightweight, anonymous method not attached to any assembly (or attached to an existing assembly)?

确定,因为人们要求的例子。

OK, since people asked for an example.

下面是一个类,用手写

class MyBusinessObject
{
    public int a;
    public string b { get; set; }
}

下面是用手工ppared一个DataTable,$ P $(在现实生活中,这将来自外部库):

Here's a DataTable, prepared by hand (in real life, this will come from an external library):

DataTable t = new DataTable();
t.AddColumn("a", typeof(int));
t.AddColumn("b", typeof(string));
t.AddRow(42, "Meaning");

下面是应该在飞行中产生的方法:

Here's the method that should be generated on the fly:

(DataRow drow, MyBusinessObject o) =>
{
    o.a = (int)drow["a"];
    o.b = (string)drow["b"];
}

我省略了一些其他的东西,我需要的简洁,但是这是问题的肉。

I've omitted some other stuff I need for brevity, but that's the meat of the issue.

推荐答案

生成$ C $最简单的方法Ç动态在.NET 3.5 +是通过转换的 LINQ防爆pression树木通过的可执行code: //msdn.microsoft.com/en-us/library/bb356928.aspx相对=nofollow> 编译 LambdaEx pression 类。 .NET 4.0,极大地拓展了可能性,加入支持超出了简单的EX $ P $的.NET 3.5 pssions code结构,使您可以构建功能齐全的方法。得到的code为您提供同样高的性能,定期编制code会,假设你的前pression发生器应用同种优化一个C#编译器会同时生成code的。

The easiest way to generate code dynamically in .NET 3.5+ is by converting LINQ Expression Trees to executable code through the Compile method of the LambdaExpression class. .NET 4.0 has greatly expanded the possibilities, adding support for code structures beyond simple expressions of .NET 3.5, letting you construct fully functional methods. The resultant code gives you the same high performance as regularly compiled code would, assuming that your expression generator has applied the same kinds of optimizations a C# compiler would while generating the code.

下面是如何,你可以根据你的代码段code:

Here is how you could generate the code from your snippet:

// nameToProperty is a dictionary with keys representing string parameters
// that you pass to drow's indexer, and values representing names of properties
// or fields of the target object.
private static Action<DataRow,T> MakeGetter<T>(IDictionary<string,string> nameToProperty) {
    var sequence = new List<Expression>();
    var drowParam = Expression.Parameter(typeof(DataRow));
    var oParam = Expression.Parameter(typeof(T));
    var indexer = typeof(DataRow)
        .GetDefaultMembers()
        .OfType<PropertyInfo>()
        .Where(pinf => pinf.GetIndexParameters().Length == 1
               &&      pinf.GetIndexParameters()[0].ParameterType == typeof(string))
        .Single();
    foreach (var pair in nameToProperty) {
        var indexExpr = Expression.Property(
            drowParam
        ,   indexer
        ,   Expression.Constant(pair.Key));
        sequence.Add(Expression.Assign(
            Expression.PropertyOrField(pair.Value)
        ,   indexExpr
        ));
    }
    return (Action<DataRow,T>)Expression.Lambda(
        Expression.Block(sequence)
    ,   drowParam
    ,   oParam
    ).Compile();
}

使用这种方法的地方,你应该能够产生编译动作取值在需要时会做的作业。

With this method in place, you should be able to generate compiled Actions that would do the assignments as needed.

这篇关于什么是动态生成code。在.NET 4.5中最简单的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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