2013-02-23 1 views
2

Это первый раз, когда я занимаюсь созданием CIL, поэтому, пожалуйста, несите свое невежество. Я ищу простой DynamicMethod, который может читать поля POCO и заполнять их в object[]. Преобразование типа не требуется. Я собрал все, что могу, могу ли вы помочь в его завершении?Как преобразовать POCO в массив с помощью CIL?

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); 
+1

Существует простое решение с использованием деревьев выражений, которое делает вас скомпилированной лямбдой. Вы были бы заинтересованы в этом, или вы ищете специально для решения emit? – dasblinkenlight

+1

Если вы хотите знать, как сделать что-то в IL, напишите тот же код на C# и посмотрите сгенерированный IL. – svick

+1

@Geotarget Я думаю, что вы путаете деревья выражений LINQ и Linq. Скомпилированные деревья выражений так же быстро, как и код, который вы испускаете вручную. – dasblinkenlight

ответ

3

Этот код можно использовать, чтобы сгенерировать скомпилированное лямбда-выражение.

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 «s Compile метод сделать это для вашего.

Адрес working demo on ideone.

+0

Удивительно! Он отлично работал. –