2009-10-20 14 views
5

Bir StringBuilder kullanan bir kod oluşturmaya çalışıyorum ve bir sınıftaki tüm özelliklerin değerlerini bir dizeye yazar. Ben aşağıdaki var ama şu anda aşağıdaki kodunda bir "Geçersiz yöntem belirteci" alıyorum:CIL (MSIL) içinde Stringbuilder

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; 
    } 

bir fikir? Teşekkür peşin :)

+0

(: Bu kadar eşdeğinde

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 

Yorum yapmak için) –

cevap

5

Değer türleri (int vb.) Olan tüm özelliklerin boks gerektirecektir; veya farklı bir Append aşırı yüklemesi kullanmanız gerekecektir. Ayrıca

:

  • nesnenin her zaman (arg0)
  • StringBuilder.Append akıcı API yüklemek gerekir; Eğer değeri pop veya gerek ya yeniden kullanmak:
  • bir sonucu olarak, alanı gerekmez

(şahsen, ama, ben bir string döneceğini, ancak "eh")

böylece gibi: cevap

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, çok güzel açıkladı. –

+0

Ah teşekkürler, bu süper bir açıklama! Boks tarafından ne demek istediğimi anlıyorum, derleyiciye, aramak için doğru aşırı yükü otomatik olarak çözüyorum. Append tarafından ne demek istediğimi akıcı bir API olduğundan emin değilim. Bu, eklenmekte olan değerin yığından tüketilmediği anlamına mı geliyor? Ve Ldarg_0, nereden girdi? Tüm sorular için özür dilerim xD – Josh

+2

akıcı tarafından, Yani bu, "void" i döndürmez demek - bu 'döndürür; '.Append (...)' i çağırınız. Ekle (...). Ekle (...) 'vb. Her çağrıdan sonra yığında bir değer bırakıyordunuz. 'arg0' giriş parametresidir (çünkü bu statik bir yöntemdir). Bir örnek metot için 'arg0 'budur. –

İlgili konular