2009-10-20 8 views
5

StringBuilder를 사용하여 클래스의 모든 속성 값을 문자열에 씁니다. 나는 다음있어,하지만 난 현재 다음 코드에서 "잘못된 방법 토큰"을 받고 있어요 :String Builder in CIL (MSIL)

public static DynamicAccessor<T> CreateWriter(T target) //Target class to *serialize* 
    { 
     DynamicAccessor<T> dynAccessor = new DynamicAccessor<T>(); 

     MethodInfo AppendMethod = typeof(StringBuilder).GetMethod("Append", new[] { typeof(Object) }); //Append method of Stringbuilder 

     var method = new DynamicMethod("ClassWriter", typeof(StringBuilder), new[] { typeof(T) }, typeof(T), true); 
     var generator = method.GetILGenerator(); 
     LocalBuilder sb = generator.DeclareLocal(typeof(StringBuilder)); //sb pointer 


     generator.Emit(OpCodes.Newobj, typeof(StringBuilder)); //make our string builder 
     generator.Emit(OpCodes.Stloc, sb);      //make a pointer to our new sb 


     //iterate through all the instance of T's props and sb.Append their values. 
     PropertyInfo[] props = typeof(T).GetProperties(); 
     foreach (var info in props) 
     { 
      generator.Emit(OpCodes.Callvirt, info.GetGetMethod()); //call the Getter 
      generator.Emit(OpCodes.Ldloc, sb);      //load the sb pointer 
      generator.Emit(OpCodes.Callvirt, AppendMethod);  //Call Append 
     } 

     generator.Emit(OpCodes.Ldloc, sb); 
     generator.Emit(OpCodes.Ret);   //return pointer to sb 

     dynAccessor.WriteHandler = method.CreateDelegate(typeof(Write)) as Write; 
     return dynAccessor; 
    } 

어떤 아이디어? 미리 감사드립니다.

+0

(이 등가가 발생

DynamicAccessor<T> dynAccessor = new DynamicAccessor<T>(); MethodInfo AppendMethod = typeof(StringBuilder).GetMethod("Append", new[] { typeof(Object) }); //Append method of Stringbuilder var method = new DynamicMethod("ClassWriter", typeof(StringBuilder), new[] { typeof(T) }, typeof(T), true); var generator = method.GetILGenerator(); generator.Emit(OpCodes.Newobj, typeof(StringBuilder).GetConstructor(Type.EmptyTypes)); //make our string builder //iterate through all the instance of T's props and sb.Append their values. PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var info in props) { generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Callvirt, info.GetGetMethod()); //call the Getter if (info.PropertyType.IsValueType) { generator.Emit(OpCodes.Box, info.PropertyType); } generator.Emit(OpCodes.Callvirt, AppendMethod); //Call Append } generator.Emit(OpCodes.Ret); //return pointer to sb 

덧글을) –

답변

5

값 유형 (int 등) 인 모든 속성은 권투가 필요합니다. 또는 다른 Append 과부하를 사용해야합니다. 또한

:

  • 당신은 개체마다 (는 arg0)
  • StringBuilder.Append가 유창 API입니다로드해야합니다; 당신이 값을 팝업, 또는 필요 중 하나를 다시 사용 :
  • 을 결과로, 당신은 필드가 필요하지 않습니다

이 (개인적으로하지만, 나는 string을 반환 싶지만, "MEH")

그래서 같은 응답

StringBuilder ClassWriter(T obj) { 
    return new StringBuilder.Append((object)obj.Foo).Append((object)obj.Bar) 
        .Append((object)obj.Blip).Append((object)obj.Blap); 
} 
+0

+1, 매우 친절하게 설명했다. –

+0

아, 고마워,이게 슈퍼 설명이야! 나는 복싱에 의해 당신이 무슨 뜻인지 알기 때문에, 나는 정확한 호출을 자동으로 해결하는 컴파일러에 익숙하다. Append가 의미하는 것이 유창한 API인지 확실하지 않습니다. 즉, 추가되는 값이 스택에서 소비되지 않는다는 의미입니까? Ldarg_0은 어디에서 입력을 얻습니까? 모든 질문에 대해 유감스럽게 생각합니다. 유동적 인 xD – Josh

+2

으로, Append가 'void'를 반환하지 않는다는 것을 의미합니다. 'this'를 반환합니다. Append (...) Append (...) Append (...) 등 호출 할 때마다 스택에 값을 남기고있었습니다. arg0은 입력 매개 변수입니다 (정적 메소드이기 때문에). 인스턴스 메소드의 경우 'arg0'은 "this"입니다. –