【问题标题】:C# Reflection Indexed PropertiesC# 反射索引属性
【发布时间】:2010-09-22 10:12:19
【问题描述】:

我正在编写一个使用反射的克隆方法。如何使用反射检测属性是索引属性?例如:

public string[] Items
{
   get;
   set;
}

到目前为止我的方法:

public static T Clone<T>(T from, List<string> propertiesToIgnore) where T : new()
{
    T to = new T();

    Type myType = from.GetType();

    PropertyInfo[] myProperties = myType.GetProperties();

    for (int i = 0; i < myProperties.Length; i++)
    {
        if (myProperties[i].CanWrite && !propertiesToIgnore.Contains(myProperties[i].Name))
        {
            myProperties[i].SetValue(to,myProperties[i].GetValue(from,null),null);
        }
    }

    return to;
}

【问题讨论】:

  • 那不是索引属性,是返回数组的属性。
  • 这个问题需要版主修改。这是查找索引器属性的最佳 google 结果,但这不是代码示例说明的内容。下面的答案一半回答了问题,一半回答了代码示例。

标签: c# reflection clone


【解决方案1】:
if (propertyInfo.GetIndexParameters().Length > 0)
{
    // Property is an indexer
}

【讨论】:

    【解决方案2】:

    对不起,但是

    public string[] Items { get; set; }
    

    不是索引属性,它只是一个数组类型! 但是以下是:

    public string this[int index]
    {
        get { ... }
        set { ... }
    }
    

    【讨论】:

    • 好的,但是如何通过反射找到它?
    【解决方案3】:

    你想要的是GetIndexParameters() 方法。如果它返回的数组有超过 0 项,这意味着它是一个索引属性。

    更多详情请见the MSDN documentation。

    【讨论】:

      【解决方案4】:

      如果你调用property.GetValue(obj,null),并且属性被索引,那么你会得到一个参数计数不匹配的异常。最好检查该属性是否使用GetIndexParameters() 进行索引,然后决定要做什么。

      【讨论】:

        【解决方案5】:

        下面是一些对我有用的代码:

        foreach(obj.GetType().GetProperties() 中的 PropertyInfo 属性) { 对象值 = property.GetValue(obj, null); 如果(值是对象[]) { …… } }

        附: .GetIndexParameters().Length &gt; 0) 适用于本文描述的案例:http://msdn.microsoft.com/en-us/library/b05d59ty.aspx 因此,如果您关心名为 Chars 的字符串类型值的属性,请使用它,但它不适用于我感兴趣的大多数数组,包括我很确定原始问题中的字符串数组。

        【讨论】:

          【解决方案6】:

          您可以将索引器转换为 IEnumerable

              public static IEnumerable<T> AsEnumerable<T>(this object o) where T : class {
                  var list = new List<T>();
                  System.Reflection.PropertyInfo indexerProperty = null;
                  foreach (System.Reflection.PropertyInfo pi in o.GetType().GetProperties()) {
                      if (pi.GetIndexParameters().Length > 0) {
                          indexerProperty = pi;
                          break;
                      }
                  }
          
                  if (indexerProperty.IsNotNull()) {
                      var len = o.GetPropertyValue<int>("Length");
                      for (int i = 0; i < len; i++) {
                          var item = indexerProperty.GetValue(o, new object[]{i});
                          if (item.IsNotNull()) {
                              var itemObject = item as T;
                              if (itemObject.IsNotNull()) {
                                  list.Add(itemObject);
                              }
                          }
                      }
                  }
          
                  return list;
              }
          
          
              public static bool IsNotNull(this object o) {
                  return o != null;
              }
          
              public static T GetPropertyValue<T>(this object source, string property) {
                  if (source == null)
                      throw new ArgumentNullException("source");
          
                  var sourceType = source.GetType();
                  var sourceProperties = sourceType.GetProperties();
                  var properties = sourceProperties
                      .Where(s => s.Name.Equals(property));
                  if (properties.Count() == 0) {
                      sourceProperties = sourceType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic);
                      properties = sourceProperties.Where(s => s.Name.Equals(property));
                  }
          
                  if (properties.Count() > 0) {
                      var propertyValue = properties
                          .Select(s => s.GetValue(source, null))
                          .FirstOrDefault();
          
                      return propertyValue != null ? (T)propertyValue : default(T);
                  }
          
                  return default(T);
              }
          

          【讨论】:

          • 我认为这只处理单整数索引器属性,对吧?没有基于字符串的索引器,没有多个索引参数……还是我遗漏了什么?
          • @CodeJockey — 你可能是对的;我无法让它与String 输入类型一起工作。它挂在Chars 索引属性上。除非我自己错过了什么……
          猜你喜欢
          • 2010-11-21
          • 1970-01-01
          • 2017-05-31
          • 2023-04-10
          • 2011-02-11
          • 2011-02-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多