2010-09-30 25 views
0

我們即將在我的公司做一些反射器。IDictionary <obj, obj> to obj使用發射器

我需要一個FactoryClass,它可以通過對屬性和字典鍵進行匹配來將IDictionary轉換爲obj。

我發現:

Dynamic object property populator (without reflection)

這個代碼可以做我想做的,我想用這個代碼,因爲它是由使用的dotnet基本不使用他人的擴展來完成。

public class Populator<T> 
{ 
    private delegate T Load(Dictionary<string, object> properties); 
    private Load _handler; 
    private Populator() { } 
    public T Build(Dictionary<string, object> properties) 
    { 
     return _handler(properties); 
    } 
public static Populator<T> CreateBuilder(Dictionary<string, object> properties) 
{ 
    //private static readonly MethodInfo getValueMethod = typeof(IDataRecord).GetMethod("get_Item", new [] { typeof(int) }); 
    //private static readonly MethodInfo isDBNullMethod = typeof(IDataRecord).GetMethod("IsDBNull", new [] { typeof(int) }); 
    Populator<T> dynamicBuilder = new Populator<T>(); 
    ... 

當我測試這段代碼時,出現錯誤。

public ICollection<object> GetKeys(IDictionary<object, object> products) 
    { 
     IDictionary<object, object> product = (IDictionary<object, object>)products.ElementAt(0).Value; 

     Dictionary<string, object> p = new Dictionary<string, object>(); 
     foreach (KeyValuePair<object, object> item in product) 
     { 
      p.Add(item.Key.ToString(), item.Value); 
     } 

     Populator<ProductTest> builder = Populator<ProductTest>.CreateBuilder(p); 
     ProductTest obj = builder.Build(p); // error here 


     return null; 
    } 

我這裏

public class Populator<T> 
{ 
    private delegate T Load(Dictionary<string, object> properties); 
    private Load _handler; 
    private Populator() { } 
    public T Build(Dictionary<string, object> properties) 
    { 
     return _handler(properties); // Error: JIT Compiler encountered an internal limitation. 
    } 

Wy的問題的錯誤是爲什麼,以及如何解決呢? 堆棧跟蹤中沒有額外的東西。

//丹尼斯

+0

的問題肯定是產生了'Load'委託的代碼,但你沒有張貼的一部分,所以我們不能真正幫助你... – 2010-09-30 12:25:01

+0

這是一個利益例外,但它是完全不可能用所提供的代碼重新編制它。很不清楚_handler是如何初始化的。如果你使用任何Reflection.Emit,那麼你只是搞砸了IL。 – 2010-09-30 12:34:52

回答

0

下面是一些測試代碼的類,以及與該錯誤的映射器。 你只需要啓動klasse。

// http://stackoverflow.com/questions/1273589/dynamic-object-property-populator-without-reflection 

namespace Test 

{ 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 

using System.Reflection; 
using System.Reflection.Emit; 


public class ProductTest 
{ 

    public string ProductGuid { get; set; } 
    public string ProductName { get; set; } 

} 

/// <summary> 
/// Summary description for ProductMapper 
/// </summary> 
public class ProductMapper 
{ 
    public ProductMapper() 
    { 
     DoTheMagic(); 
    } 
    public ICollection<object> DoTheMagic() 
    { 
     Dictionary<string, object> product = new Dictionary<string, object>(); 


     product["ProductGuid"] = "Product Id"; 
     product["ProductName"] = "Product Name"; 


     Populator<ProductTest> builder = Populator<ProductTest>.CreateBuilder(product); 
     ProductTest obj = builder.Build(product); 


     return null; 
    } 
} 




public class Populator<T> 
{ 
    private delegate T Load(Dictionary<string, object> properties); 
    private Load _handler; 
    private Populator() { } 
    public T Build(Dictionary<string, object> properties) 
    { 
     T obj = default(T); 
     try 
     { 
      obj = _handler(properties); // JIT Compiler encountered an internal limitation. 
     } 
     catch (Exception ex) 
     { 
      string s = ex.Message; 
     } 

     return obj; 
    } 
    public static Populator<T> CreateBuilder(Dictionary<string, object> properties) 
    { 
     //private static readonly MethodInfo getValueMethod = typeof(IDataRecord).GetMethod("get_Item", new [] { typeof(int) }); 
     //private static readonly MethodInfo isDBNullMethod = typeof(IDataRecord).GetMethod("IsDBNull", new [] { typeof(int) }); 
     Populator<T> dynamicBuilder = new Populator<T>(); 
     DynamicMethod method = new DynamicMethod("Create", typeof(T), new[] { typeof(Dictionary<string, object>) }, typeof(T), true); 
     ILGenerator generator = method.GetILGenerator(); 

     LocalBuilder result = generator.DeclareLocal(typeof(T)); 
     generator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes)); 
     generator.Emit(OpCodes.Stloc, result); 

     int i = 0; 
     foreach (var property in properties) 
     { 
      PropertyInfo propertyInfo = typeof(T).GetProperty(property.Key, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy | BindingFlags.Default); 
      Label endIfLabel = generator.DefineLabel(); 

      if (propertyInfo != null && propertyInfo.GetSetMethod() != null) 
      { 
       generator.Emit(OpCodes.Ldarg_0); 
       generator.Emit(OpCodes.Ldc_I4, i); 
       //generator.Emit(OpCodes.Callvirt, isDBNullMethod); 
       generator.Emit(OpCodes.Brtrue, endIfLabel); 

       generator.Emit(OpCodes.Ldloc, result); 
       generator.Emit(OpCodes.Ldarg_0); 
       generator.Emit(OpCodes.Ldc_I4, i); 
       //generator.Emit(OpCodes.Callvirt, getValueMethod); 

       generator.Emit(OpCodes.Unbox_Any, property.Value.GetType()); 
       generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod()); 
       generator.MarkLabel(endIfLabel); 
      } 
      i++; 
     } 

     generator.Emit(OpCodes.Ldloc, result); 
     generator.Emit(OpCodes.Ret); 

     dynamicBuilder._handler = (Load)method.CreateDelegate(typeof(Load)); 
     return dynamicBuilder; 
    } 
} 

} 

希望這會有所幫助。

+0

嗨,歡迎來到堆棧溢出,但請編輯您的問題並刪除它。這不是一個真正的討論板,所以這個答案很快就會在其他答案之下/之間下降。現在看起來您已經回答了您的問題,而不是爲您的問題提供更多信息。只是擡頭:) – 2010-10-01 09:06:25

+0

如何添加內容。 – 2010-10-01 10:13:39

+0

我不能在評論欄中做到這一點,它是小的:S – 2010-10-01 10:14:00

相關問題