2013-02-23 5 views
2

생성 된 CIL로 처음 보니 제 무지와 함께 견뎌주십시오. 나는 POCO의 필드를 읽고 object[]으로 채울 수있는 간단한 DynamicMethod를 찾고있다. 유형 변환은 필요하지 않습니다. 내가 할 수있는 모든 것을 모아 봤어, 그걸 완성하도록 도와 줄 수 있니?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

표현 트리를 사용하는 간단한 해결책이 있습니다. 그러면 컴파일 된 람다가됩니다. 관심을 보이시겠습니까? 아니면 특별히 방출 솔루션을 찾고 계십니까? – 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을 생산하고, 대신 수동으로 작성하는, 그것은 LambdaCompile 방법은 당신을 위해 그것을 할 수 있습니다.

여기는 working demo on ideone입니다.

+0

놀라운! 그것은 완벽하게 작동했습니다. –

관련 문제