【问题标题】:Reflection help. Make a collection from a class based on its properties?反思帮助。根据其属性从一个类中创建一个集合?
【发布时间】:2010-12-04 09:22:51
【问题描述】:

我需要一点帮助。我对反思还很陌生。我们正在使用第 3 方 api,它返回一个名为“AddressList”的类。它内部有公共属性,字面上称为 Address1、Address1Name、Address1Desc、Address2、Address2Name、Address2Desc、Address3、Address3Name、Address3Desc、... Address99、Address99Name、Address99Desc.. 还有一些其他属性。我有一个名为“SimpleAddress”的类,它只有 3 个属性(地址、名称、描述)。我想要做的是当我得到“AddressList”类返回时,我想通过AddressDesc99循环AddressDesc1 ...并且无论哪个不为null或为空,我想创建一个“SimpleAddress”实例,填充它的属性,并将其添加到列表中...有人可以指出我正确的方向吗?显然,如果“AddressList”是某种集合,这会更好,但不幸的是它不是。它是从大型机的返回字符串生成的。

感谢您的帮助, ~ck 在圣地亚哥

【问题讨论】:

    标签: c# reflection collections


    【解决方案1】:

    咳咳。你可以这样做:

    List<SimpleAddress> addresses = new List<SimpleAddress>();
    
    string addressPropertyPattern = "Address{0}";
    string namePropertyPattern = "Address{0}Name";
    string descPropertyPattern = "Address{0}Desc";
    
    for(int i = 1; i <= MAX_ADDRESS_NUMBER; i++)
    {
        System.Reflection.PropertyInfo addressProperty = typeof(AddressList).GetProperty(string.Format(addressPropertyPattern, i));
        System.Reflection.PropertyInfo nameProperty = typeof(AddressList).GetProperty(string.Format(namePropertyPattern, i));
        System.Reflection.PropertyInfo descProperty = typeof(AddressList).GetProperty(string.Format(descPropertyPattern, i));
    
        SimpleAddress address = new SimpleAddress();
    
        address.Address = (string)addressProperty.GetValue(yourAddressListObject, null);
        address.Name = (string)nameProperty.GetValue(yourAddressListObject, null);
        address.Description = (string)descProperty.GetValue(yourAddressListObject, null);
    
        addresses.Add(address);
    }
    

    【讨论】:

      【解决方案2】:

      首先获取相关类的类型并调用 GetProperties 方法。

      PropertyInfo[] properties = myMainframeObject.GetType().GetProperties();
      

      每个 PropertyInfo 都有一个 Name 属性(一个字符串),您可以使用它来匹配。循环遍历所有属性,并编写创建 SimpleAddress 新实例的代码。

      在这个循环中,您可以访问您的大型机对象并提取您需要的属性值:

      // imagine that in this case, 'p' is a PropertyInfo that represents Address2Name
      var simpleAddress = new SimpleAddress();
      simpleAddress.Name = p.GetValue(myMainframeObject, null);
      

      (null 永远不会用于普通属性 - 它旨在与索引属性一起使用)。

      【讨论】:

        【解决方案3】:

        您应该能够执行以下操作:

        List<SimpleAddress> CreateList(AddressList address)
        {
            List<SimpleAddress> values = new List<SimpleAddress>();
            Type type = address.GetType();
            for (int i=1;i<=99;++i)
            {
                 string address = type.GetProperty("Address" + i.ToString()).GetValue(address,null).ToString();
                 string addressDesc = type.GetProperty("Address" + i.ToString() + "Desc").GetValue(address,null).ToString();
                 string addressName = type.GetProperty("Address" + i.ToString() + "Name").GetValue(address,null).ToString();
        
        
                 if (!string.IsNullOrEmpty(addressDesc) || !string.IsNullOrEmpty(addressName) || !string.IsNullOrEmpty(address)  )
                      value.Add(new SimpleAddress(address,addressDesc,addressName));
            }
        
            return values;
         }
        

        【讨论】:

        • 他试图提取所有三个字段。
        • 是的,我一完成就修好了。第一次忘记了。谢谢。
        【解决方案4】:

        未经测试(原因很明显),但类似:

        List<SimpleAddress> newList = new List<SimpleAddress>();
        AddressList list = ...
        Type type = list.GetType();
        PropertyInfo prop1, prop2, prop3;
        int index = 1;
        while((prop1 = type.GetProperty("Address" + index)) != null
           && (prop2 = type.GetProperty("Address" + index + "Name")) != null
           && (prop3 = type.GetProperty("Address" + index + "Desc")) != null) {
            string addr = (string) prop1.GetValue(list, null),
                   name = (string) prop2.GetValue(list, null),
                   desc = (string) prop3.GetValue(list, null);
        
            if(addr == null || name == null || desc == null) {
               continue; // skip but continue
            }
        
            SimpleAddress newAddr = new SimpleAddress(addr, name, desc);
            newList.Add(newAddr);
            index++;
        }
        

        【讨论】:

          【解决方案5】:

          如果你想使用 linq

          public static class MyTools
          {
              public static TReturn GetValue<TReturn>(this object input, 
                                                      string propertyName)
              {
                  if (input == null)
                      return default(TReturn);
                  var pi = input.GetType().GetProperty(propertyName);
                  if (pi == null)
                      return default(TReturn);
                  var val = pi.GetValue(input, null);
                  return (TReturn)(val == null ? default(TReturn) : val);
              }
          
              public static string GetString(this object input, string propertyName)
              {
                  return input.GetValue<string>(propertyName);
              }
          
              public static List<SimpleAddress> GetAddress(this MyObject input)
              {
                  return (
                      from i in Enumerable.Range(1, 2)
                      let address = input.GetString("Address" + i.ToString())
                      let name = input.GetString("Address" + i.ToString() + "Name")
                      let desc = input.GetString("Address" + i.ToString() + "Desc")
                      select new SimpleAddress() { Address = address, 
                                                   Name = name, 
                                                   Description = desc }
                     ).ToList();
              }
          }
          

          【讨论】:

          • 这种扩展方法不是一个坏主意。让它通用,你会得到我的 +1。
          • @Adam:对于这样的输出?
          • @Matthew:+1。没错,虽然我根本不会把 GetString 放在那里,因为它除了调用 GetValue&lt;string&gt; 之外什么也没做。
          • 我把它留在那里是因为我不想修复它下面的代码。
          【解决方案6】:
          var addrList = new AddressList
          {
              Address1Name = "ABC",
              Address1Desc = "DEF",
              Address1 = "GHI",
              Address3Name = "X",
              Address3Desc = "Y",
              Address3 = "Z"
          };
          
          var addresses =
                  from i in Enumerable.Range(1, 99)
                  let desc = typeof(AddressList).GetProperty(string.Format("Address{0}Desc", i)).GetValue(addrList, null) as string
                  let name = typeof(AddressList).GetProperty(string.Format("Address{0}Name", i)).GetValue(addrList, null) as string
                  let address = typeof(AddressList).GetProperty(string.Format("Address{0}", i)).GetValue(addrList, null) as string
                  where !string.IsNullOrEmpty(address)
                  select new SimpleAddress
                  {
                      Name = name,
                      Description = desc,
                      Address = address
                  };
          

          【讨论】:

          • 我想我应该先仔细看看你的答案......哦,我只是将部分代码移到扩展方法中以更好地重用它。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-08-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多