IDictionary <obj, obj> для obj с использованием emit - PullRequest
0 голосов
/ 30 сентября 2010

Мы собираемся сделать отражатель в моей компании.

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

IНайдено:

Свойство динамического свойства объекта (без отражения)

Этот код может делать то, что я хочу, и я хочу использовать этот код, потому что это делается с помощьюосновы 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.
    }

Тогда возникает вопрос, почему и как это решить?В трассировке стека нет ничего лишнего.

// dennis

1 Ответ

0 голосов
/ 01 октября 2010

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

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

}

Надеюсь, это поможет.

...