Home > Back-end >  Is there any simple method for assigning values from inside to list to a model?
Is there any simple method for assigning values from inside to list to a model?

Time:12-26

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