0

Имея класс определен:Создать объект .NET с DataContract из словаря

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

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

Я хотел бы создать экземпляр этого класса из словаря:

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

DataContractSerializer не работает для я и не JavaScriptSerializer.ConvertToType, так как в каждой из них отсутствует кусок, который останавливает меня от создания объектов за один раз.

+3

Не могли бы вы использовать команду 'var command = new Command {CommandName =" cmd1 ", CommandTransactionId =" 1 "};'? –

+0

Это значительно упрощено (просто пример). У меня есть 30 классов DataContract и 300 таких свойств. Вместо DataMember я мог бы использовать JsonProperty, например. – algorytmus

+0

Что бы я, наверное, первым попробовал, это взять словарь свойств. Преобразуйте эти «объекты» в строку JSON. Затем преобразуйте эту строку JSON в фактический класс объекта. С помощью этого шаблона вы в основном воссоздаете поведение JSON от клиента к серверу по API или из данных формы. – krillgar

ответ

2

JavaScriptSerializer будет работать здесь с некоторыми изменениями:

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

Я использовал Deserialize метод вместо ConvertToType один. Второе различие более значимо. Используемый мной словарь содержит ключи, которые совпадают с именами свойств в классе Command. Если вам это не нравится, попробуйте написать обычай JavaScriptConverter. См. Это question.

+0

Вы пытались использовать решения, предложенные в вопросе, указанном мной? Мне кажется, что они не требуют переименования ключей или свойств. –

+0

Я не могу изменить ключи в словаре свойствBag (они создаются другими компонентами, из которых у меня нет контроля), поэтому это не сработает для меня («cmdName»! = «CommandName»). Я не могу переименовать свои свойства. – algorytmus

0

Может быть, вы можете попробовать этот код 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; 
} 

Этот код не тестировался - просто напечатал здесь.

Смежные вопросы