I have 2 models like this
public class ModelA
{
public string Name{get;set;}
public string Value{get;set;}
}
public class B
{
public List<ModelA>Items{get;set;}
}
The below input will be deserialized onto class B
{
"Items":[
{
"Name":"Food Name"
"Value":"Fries"
},
{
"Name":"Weapon Name"
"Value":"Gun"
},
{
"Name":"Vehicle Name"
"Value":"Car"
}
]
}
I have another third model like below
public class ModelValues
{
public string FoodName{get;set;}
public string WeaponName{get;set;}
public string VehicleName{get;set;}
}
I want to add the corresponding values of model A onto ModelValues class, like the value of FoodName property should get as Fries. Is there any simple way to assign the values of that class A to ModelValues. i know that we can use something like
public void AssignValues(B products)
{
ModelValues values=new ModelValues();
values.FoodName=products.Find(x=>x.Name=="Food Name").Value;
values.WeaponName=products.Find(x=>x.Name=="Weapon Name").Value;
}
In actual implementation since the items in ModelValues and the input will large i would like to avoid such line by line assigning of values. is there any ways to get this done with just few lines of code
CodePudding user response:
Another one variation of a Newtonsoft.Json usage:
public class ModelValues
{
[JsonProperty("Food Name")]
public string FoodName { get; set; }
[JsonProperty("Weapon Name")]
public string WeaponName { get; set; }
[JsonProperty("Vehicle Name")]
public string VehicleName { get; set; }
}
var items = JsonConvert.DeserializeObject<B>(json)
.Items
.ToDictionary(x => x.Name, x => x.Value);
JObject obj = JObject.FromObject(items);
var values = obj.ToObject<ModelValues>();
Or with no changes to ModelValues:
var items = JsonConvert.DeserializeObject<B>(json)
.Items
.ToDictionary(x => x.Name.Replace(" ", ""), x => x.Value);
JObject obj = JObject.FromObject(items);
var values = obj.ToObject<ModelValues>();
CodePudding user response:
I would question your current approach. When you could end up adding any number of properties, a collection might be a better choice. Perhaps even a dictionary.
However, the following method will copy the values the way you want. It's not the fastest way to do this. But it will continue to work even when you add additional names and properties.
void Convert(B items, ModelValues values)
{
Type type = typeof(ModelValues);
foreach (ModelA item in items.Items)
{
string name = item.Name.Replace(" ", string.Empty);
PropertyInfo info = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public);
if (info != null)
info.SetValue(values, item.Value);
}
}
CodePudding user response:
Your code makes a list iteration for 3 times. This code only ones
var items = Newtonsoft.Json.JsonConvert.DeserializeObject<B>(json);
var values = AssignValues(items);
public ModelValues AssignValues(B products)
{
ModelValues values = new ModelValues();
foreach (var item in products.Items)
{
if (item.Name == "Food Name") values.FoodName = item.Value;
else if (item.Name == "Weapon Name") values.WeaponName = item.Value;
else values.VehicleName = item.Value;
}
return values;
}
I don't think that is a good idea, but you can use reflections to do the same
public ModelValues AssignValues(B products)
{
var dict=products.Items.ToDictionary(i => i.Name, i=> i.Value );
var values = new ModelValues();
var properties = values.GetType().GetProperties();
foreach (var prop in properties)
{
var nameIndex=prop.Name.LastIndexOf("Name");
var name= prop.Name[0..nameIndex] " Name";
prop.SetValue(values,dict[name] );
}
return values;
}
