2010-09-30 2 views
0

Мы собираемся сделать какой-то отражатель в моей компании.IDictionary <obj, obj> to obj using emit

Мне нужен FactoryClass, который может преобразовать IDictionary в obj, выполнив соответствие по свойствам и клавишам dict.

я нашел:

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', но вы не разместили эту часть, поэтому мы не можем вам помочь ... –

+0

Это интересное исключение, но полностью невозможно воспроизведите его с предоставленным кодом. Очень неясно, как _handler инициализируется. Если вы используете какой-либо Reflection.Emit, тогда вы просто испортили IL. –

ответ

0

Вот класс с некоторым тестовым кодом, и картограф с ошибкой. Вам нужно только начать класирование.

// 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

Привет, приветствуйте Stack Overflow, но, пожалуйста, отредактируйте это в свой вопрос и удалите его. SO на самом деле не является дискуссионным форумом, поэтому этот ответ быстро упадет ниже/между другими ответами. Теперь похоже, что вы ответили на свой вопрос, вместо того, чтобы предоставить больше информации для вашего вопроса. Просто голова :) –

+0

Как добавить контент. –

+0

Я не могу сделать это в поле комментариев, это мало: S –

Смежные вопросы