IDictionary <obj,obj =“”> obj使用emit </obj,>

时间:2010-09-30 11:51:50

标签: c# dictionary reflection.emit

我们即将在我的公司做一些反射器。

我需要一个可以通过对属性和字典键进行匹配来将IDictionary转换为obj的FactoryClass。

我找到了:

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问题是为什么,以及如何解决它? 堆栈跟踪中没有额外的内容。

// dennis

1 个答案:

答案 0 :(得分: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;
    }
}

}

希望这有帮助。