【问题标题】:IDictionary<obj, obj> to obj using emitIDictionary<obj, obj> 使用 emit 到 obj
【发布时间】:2010-09-30 11:51:49
【问题描述】:

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

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

//丹尼斯

【问题讨论】:

  • 问题肯定出在生成 Load 委托的代码中,但您没有发布该部分,所以我们无法真正帮助您...
  • 这是一个兴趣例外,但完全不可能用提供的代码重现它。非常不清楚 _handler 是如何初始化的。如果您使用任何 Reflection.Emit,那么您只是搞砸了 IL。

标签: c# dictionary reflection.emit


【解决方案1】:

这是带有一些测试代码的类,以及带有错误的映射器。 你只需要初始化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;
    }
}

}

希望这会有所帮助。

【讨论】:

  • 您好,欢迎来到 Stack Overflow,但请将其编辑到您的问题中并将其删除。 SO 并不是真正的讨论板,因此这个答案将很快落在其他答案之下/之间。现在看起来您回答了您的问题,而不是为您的问题提供更多信息。只是一个提示:)
  • 评论区不行,太小了:S
猜你喜欢
  • 1970-01-01
  • 2011-11-16
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多