0

Ayant une classe définie:Créer un objet .NET avec DataContract d'un dictionnaire

[DataContract] 
public class Command 
{ 
     [DataMember(Name = "cmdName")] 
     public string CommandName { get; set; } 

     [DataMember(Name = "cmdTransactionId")] 
     public string CommandTransactionId { get; set; } 
} 

Je voudrais créer une instance de cette classe d'un dictionnaire:

Dictionary<string, object> propertyBag = new Dictionary<string, object>(); 
propertyBag["cmdName"] = "cmd1"; 
propertyBag["cmdTransactionId"] = "1"; 
Command command = deserializer.Create<Command>(propertyBag); 

DataContractSerializer ne fonctionne pas pour moi non plus le JavaScriptSerializer.ConvertToType car chacun d'eux manque un morceau qui m'empêche de créer des objets en une fois.

+3

Pourriez-vous utiliser 'var command = new Commande {CommandName =" cmd1 ", CommandTransactionId =" 1 "};'? –

+0

Ceci est considérablement simplifié (juste un exemple) J'ai 30 classes DataContract et 300 propriétés comme celle-ci. Au lieu de DataMember, je pourrais utiliser JsonProperty par exemple. – algorytmus

+0

Ce que je vais probablement essayer d'abord est de prendre votre dictionnaire de propriétés. Convertir ces "objets" en une chaîne JSON. Puis convertissez cette chaîne JSON à la classe d'objet réelle. Avec ce modèle, vous recréez essentiellement le comportement client-serveur de JSON sur une API ou à partir de données de formulaire. – krillgar

Répondre

2

JavaScriptSerializer travaillera ici avec quelques changements:

var propertyBag = new Dictionary<string, object>(); 
propertyBag["CommandName"] = "cmd1"; 
propertyBag["CommandTransactionId"] = "1"; 

var serializer = new JavaScriptSerializer(); 
var res = serializer.Serialize(propertyBag); 

var command = serializer.Deserialize<Command>(res); 

I utilisé Deserialize méthode au lieu de ConvertToType un. La deuxième différence est plus significative. Un dictionnaire utilisé par moi contient des clés qui sont les mêmes que les noms de propriétés dans la classe Command. Si vous ne l'aimez pas, vous devriez essayer d'écrire un JavaScriptConverter personnalisé. Voir ce question.

+0

Avez-vous essayé d'utiliser les solutions proposées dans la question que j'ai indiquée? Il me semble qu'ils ne nécessitent pas de renommer des clés ou des propriétés. –

+0

Je ne peux pas changer les clés dans le dictionnaire propertyBag (elles sont produites par d'autres composants dont je n'ai pas le contrôle) donc cela ne fonctionnera pas pour moi ("cmdName"! = "CommandName"). Je ne peux pas renommer mes propriétés non plus. – algorytmus

0

Peut-être que vous pouvez essayer ce code pour deserializer.Create<Command>(propertyBag):

public T Create<T>(IDictionary<string, object> propertyBag) 
{ 
    var result = (T)FormatterServices.GetUninitializedObject(typeof(T)); 

    foreach (var item in from member in typeof(T).GetMembers() 
         let dataMemberAttr = member.GetCustomAttributes(typeof(DataMemberAttribute), true).Cast<DataMemberAttribute>().SingleOrDefault() 
         where dataMemberAttr != null && propertyBag.ContainsKey(dataMemberAttr.Name) 
         select new { Member = member, Value = propertyBag[dataMemberAttr.Name] }) 
    { 
     var property = item.Member as PropertyInfo; 
     if (property != null) 
     { 
      property.SetValue(result, item.Value, null); 
      continue; 
     } 

     var field = item.Member as FieldInfo; 
     if (field != null) 
     { 
      field.SetValue(result, item.Value); 
      continue; 
     } 
    } 

    return result; 
} 

Ce code n'a pas été testé - juste tapé ici.