Vil*_*lx- 7 .net code-generation
我正在编写一种特定的对象映射器.基本上我想从一个转换DataTable,其具有的字段a,b并c以具有属性的对象a,b并且c(该对象的类别的将由手写).将有许多不同的DataTable和许多不同的类需要映射到,所以我想制作一个执行此数据复制的通用机制.基本上,我想要以下功能:
public T Map<T>(DataTable t) where T: new() { ... }
Run Code Online (Sandbox Code Playgroud)
现在,我可以用Reflection做到这一点,但这很慢.该功能将成为框架的核心,并将经常使用.所以我在考虑动态代码生成.第一次在特定的方法上运行此方法时T,它将执行必要的反射并发出一个匿名方法,该方法执行所有适当的映射.下次它将运行该代码.这应该尽可能高效.
只有一个问题 - 我从未在运行时发出代码.我怎么做?我看了Expressions,但他们只能表达,而不是一系列的陈述.
然后是CodeDOM和CSharpCodeProvider.那种工作 - 我可以生成C#代码作为字符串,在运行中编译它然后获得引用.但它涉及C#编译器并生成一个全新的内存中程序集.听起来有点......重量级的一个简单的方法.
有一些更简单的方法吗?生成轻量级匿名方法的东西没有附加到任何程序集(或附加到现有程序集)?
好的,因为人们问了一个例子.
这是一个手工编写的课程
class MyBusinessObject
{
public int a;
public string b { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这是一个手工准备的DataTable(在现实生活中,它将来自一个外部库):
DataTable t = new DataTable();
t.AddColumn("a", typeof(int));
t.AddColumn("b", typeof(string));
t.AddRow(42, "Meaning");
Run Code Online (Sandbox Code Playgroud)
这是应该动态生成的方法:
(DataRow drow, MyBusinessObject o) =>
{
o.a = (int)drow["a"];
o.b = (string)drow["b"];
}
Run Code Online (Sandbox Code Playgroud)
为了简洁起见,我省略了其他一些我需要的东西,但这是问题的关键.
在.NET 3.5+中动态生成代码的最简单方法是通过类的方法将LINQ表达式树转换为可执行代码..NET 4.0极大地扩展了可能性,增加了对.NET 3.5简单表达式之外的代码结构的支持,使您可以构建功能完备的方法.结果代码为您提供与常规编译代码相同的高性能,假设您的表达式生成器在生成代码时应用了C#编译器所需的相同类型的优化.CompileLambdaExpression
以下是从代码段生成代码的方法:
// 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();
}
Run Code Online (Sandbox Code Playgroud)
使用此方法,您应该能够生成可Action根据需要执行分配的已编译s.
| 归档时间: |
|
| 查看次数: |
2208 次 |
| 最近记录: |