2010-09-30 5 views
0

Nous sommes sur le point de faire un réflecteur dans mon entreprise.IDictionary <obj, obj> à obj en utilisant l'émission

J'ai besoin d'une FactoryClass qui peut convertir un IDictionary en obj, en faisant correspondre les propriétés et les clés dict.

Je trouve:

Dynamic object property populator (without reflection)

Ce code peut faire ce que je veux, et je veux utiliser ce code, parce qu'il est fait en utilisant la base de dotNET sans utiliser les extensions des autres.

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>(); 
    ... 

Lorsque j'ai testé ce code, j'ai reçu une erreur.

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

je suis arrivé et erreur ici

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. 
    } 

question Wy est pourquoi, et comment le résoudre? Il n'y a rien en extra dans la pile.

// dennis

+0

Le problème est certainement dans le code qui génère le délégué 'Load', mais vous n'avez pas publié cette partie, donc nous ne pouvons pas vraiment vous aider ... –

+0

C'est une exception d'intérêt mais il est complètement impossible de repro le avec le code fourni. Très peu clair comment _handler est initialisé. Si vous utilisez Reflection.Emit alors vous venez de foirer l'IL. –

Répondre

0

Voici la classe avec un code de test, et le cartographe avec l'erreur. Vous avez seulement besoin de lancer la 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; 
    } 
} 

} 

Espérons que cela aide.

+0

Salut, et bienvenue à Stack Overflow, mais s'il vous plaît modifier cela dans votre question et supprimez-le. SO n'est pas vraiment un forum de discussion, donc cette réponse tombera rapidement en dessous/entre les autres réponses. Maintenant, il semble que vous avez répondu à votre question, au lieu de fournir plus d'informations pour votre question. Juste une tête :) –

+0

Comment puis-je ajouter le contenu. –

+0

Je ne peux pas le faire dans le champ de commentaire, il est trop petit: S –