【问题标题】:C# - How to assign a property value to a object without explicitly calling the property nameC# - 如何在不显式调用属性名称的情况下将属性值分配给对象
【发布时间】:2018-05-11 00:46:49
【问题描述】:

我有一个应用程序,其中有一个包含 100 个属性值的类

例如。

Class RequestData{
 String PropertName1 {get;set;}
 String PropertName2 {get;set;}
 String PropertName3 {get;set;}
 .
 .
 .
 String PropertName100 {get;set;}
}

我有一个列表>,其中包含所有属性名和属性值。所以,理想情况下,这有

PropertName1 = "Timothy"
PropertName2 = "rajan"
.
.
.
PropertName100 = "alex"

我需要创建一个 RequestData 实例并将所有属性值分配给每个属性名称

在这种情况下,我需要这样做,这将导致 100 行

 RequestData requestData = new RequestData ();
 requestData.PropertName1 = "Timothy" ;
 requestData.PropertName2 = "Rajan" ;
 requestData.PropertName3 = "Alex" ;

有没有更好的方法来做到这一点?我可以循环进入列表,但不知道如何巧妙地做到这一点

 RequestData requestData = new RequestData ();
 requestData.[key]= value ;

我希望我说清楚了。任何帮助都会很棒。

【问题讨论】:

  • 如果您只是创建一个请求对象,为什么不使用ExpandoObject - 您可以将其视为字典或对象。
  • 您还没有显示列表,您已经显示了看起来像是多个作业的内容。您能否显示“属性名称和值列表”的实际示例?是不是类似于var propNamesAndValues = new List<string> { "PropertName1 = Timothy", "PropertName2 = rajan", ... , "PropertName100 = alex" };
  • 另一个想法,如果您可以获取 JSON 格式的输入,那么您可以使用 Newtonsoft.Json 并将其反序列化到您的 RequestData 对象中。
  • 正如@gilliduck 所指出的,如果没有更多关于您要达到的目标的上下文,这个问题并不能真正回答。例如,您所说的“RequestData”是什么?如果属性名称匹配,也许您可​​以使用 AutoMapper 或其他库。

标签: c# .net dictionary


【解决方案1】:

是的,你可以做到。如果没有更多细节,尽管很难给出“好的”回应。根据您所展示的内容(并且我可能做出了错误的假设),这是几种不同的可能方法之一。我个人并不真正推荐这个,但也许它(连同其他答案/cmets)会让你走上你真正想要/需要走的路。

我应该提到,有更有效的方法可以解决这个问题,但我想展示一种基本方法,可能更清楚地了解实际发生的情况。

    static void Main()
    {
        var propertyList = new List<KeyValuePair<string, string>>
        {
            new KeyValuePair<string, string>("PropertyName1","Value1"),
            new KeyValuePair<string, string>("PropertyName2","Value2"),
            new KeyValuePair<string, string>("PropertyName3","Value3"),
            new KeyValuePair<string, string>("PropertyName4","Value4"),
            new KeyValuePair<string, string>("PropertyName5","Value5"),
        };

        var requestData = new RequestData();
        //reflection allows you to loop through the properties of a class
        foreach (var property in requestData.GetType().GetProperties())
        {
            //you can loop through your list (here I made an assumption that it's a list of KeyValuePair)
            foreach (var keyValuePair in propertyList)
            {
                //if the key matches the property name, assign the value
                if (property.Name.Equals(keyValuePair.Key))
                {
                    property.SetValue(requestData, keyValuePair.Value);
                }
            }
        }

        //to show that they are properly set
        Console.WriteLine(requestData.PropertyName1);
        Console.WriteLine(requestData.PropertyName2);
        Console.WriteLine(requestData.PropertyName3);
        Console.WriteLine(requestData.PropertyName4);
    }
}

public class RequestData
{
    public string PropertyName1 { get; set; }
    public string PropertyName2 { get; set; }
    public string PropertyName3 { get; set; }
    public string PropertyName4 { get; set; }
}

【讨论】:

    【解决方案2】:

    将另一个类似的答案扔到环中,这个使用字符串列表并将它们拆分在=符号上,然后使用反射尝试获取属性名称,如果不为空,则将属性值设置为我们的对象:

    private static void Main()
    {
        var propNamesAndValues = new List<string>
        {
            "PropertName1 = Timothy",
            "PropertName2 = Rajan",
            "PropertName100 = Alex",
        };
    
        var requestData = new RequestData();
    
        foreach (var propNameValue in propNamesAndValues)
        {
            var parts = propNameValue.Split('=');
            if (parts.Length < 2) continue;
    
            var propName = parts[0].Trim();
            var propValue = parts[1].Trim();
    
            typeof(RequestData).GetProperty(propName)?.SetValue(requestData, propValue);
        }
    
        Console.WriteLine("{0} {1} {2}", requestData.PropertName1,
            requestData.PropertName2, requestData.PropertName100);
    
        GetKeyFromUser("\nDone! Press any key to exit...");
    }
    

    输出

    【讨论】:

      【解决方案3】:

      你可以通过反射来做到这一点

      _list = new List<Tuple<string, string>>
         {
            new Tuple<string, string>("PropertName1", "asd"),
            new Tuple<string, string>("PropertName2", "sdfgds"),
            new Tuple<string, string>("PropertName3", "dfgdfg"),
            new Tuple<string, string>("PropertName100", "dfgdfg")
         };
      
      
      var requestData = new RequestData();
      
      foreach (var tuple in _list)
      {
         requestData.GetType()
                    .GetProperty(tuple.Item1, BindingFlags.Public| BindingFlags.NonPublic | BindingFlags.Instance )
                   ?.SetValue(requestData, tuple.Item2);
      
      }
      

      或者扩展方法

      public void UpdateProperties<T>(this T obj, List<Tuple<string, string>> list) where T : class
      {
         foreach (var tuple in _list)
         {
            var type = obj.GetType();
               var property = type.GetProperty(tuple.Item1, BindingFlags.Public| BindingFlags.NonPublic | BindingFlags.Instance );
            if(property == null)
               continue;
            property.SetValue(obj, tuple.Item2);
         }
      }
      

      Full Demo here

      其他资源

      Type.GetProperty Method (String)

      搜索具有指定名称的公共属性。

      PropertyInfo.SetValue Method (Object, Object)

      设置指定对象的属性值。

      BindingFlags Enumeration

      指定控制绑定和搜索方式的标志 对于成员和类型是通过反射进行的。

      【讨论】:

        猜你喜欢
        • 2011-02-17
        • 2017-12-04
        • 1970-01-01
        • 2013-05-10
        • 1970-01-01
        • 1970-01-01
        • 2014-04-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多