这是我第一次涉足生成的CIL,所以请忍受我的无知。我正在寻找一个简单的DynamicMethod,它可以读取POCO的字段,并将它们填入object[]
。不需要类型转换。我把所有的东西放在一起,你能帮忙完成它吗?
Type t = typeof(POCO);
DynamicMethod dm = new DynamicMethod("Get" + memberName,typeof(MemberType), new Type[] { objectType }, objectType);
ILGenerator il = dm.GetILGenerator();
// Load the instance of the object (argument 0) onto the stack
il.Emit(OpCodes.Ldarg_0);
// get fields
FieldInfo[] fields = t.GetFields();
// how do I create an array (object[]) at this point?
// per field
foreach (var pi in fields) {
// Load the value of the object's field (fi) onto the stack
il.Emit(OpCodes.Ldfld, fi);
// how do I add it into the array?
}
// how do I push the array onto the stack?
// return the array
il.Emit(OpCodes.Ret);
答案 0 :(得分:3)
您可以使用此代码生成已编译的lambda表达式。
public static Func<T, object[]> MakeFieldGetter<T>() {
var arg = Expression.Parameter(typeof(T), "arg");
var body = Expression.NewArrayInit(
typeof(object)
, typeof(T).GetFields().Select(f => (Expression)Expression.Convert(Expression.Field(arg, f), typeof(object)))
);
return (Func<T, object[]>)Expression
.Lambda(typeof(Func<T, object[]>), body, arg)
.Compile();
}
这相当于以下手动编写的代码:
object[] GetFields(MyClass arg) {
return new object[] {
// The list of fields is generated through reflection
// at the time of building the lambda. There is no reflection calls
// inside the working lambda, though: the field list is "baked into"
// the expression as if it were hard-coded manually.
(object)arg.Field1
, (object)arg.Field2
, (object)arg.Field3
};
}
此代码也会生成IL,但不是您手动编写,而是让Lambda
Compile
方法为您执行此操作。