2010-09-30 75 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

相关问题