2008-11-14 2 views
22

Я пишу метод Clone с использованием отражения. Как определить, что свойство является индексированным свойством с использованием отражения? Например:C# Отражение Индексированные свойства

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; 
} 
+13

Это не индексированный свойство, то есть свойство, которое возвращает массив. – 2008-11-14 21:29:04

+3

Этот вопрос должен быть изменен модератором. Это верхний результат Google для поиска свойства индексатора, но это не то, что иллюстрирует пример кода. Половина ответов ниже ответит на вопрос и наполовину пример кода. – 2015-02-21 17:35:33

ответ

40
if (propertyInfo.GetIndexParameters().Length > 0) 
{ 
    // Property is an indexer 
} 
8

То, что вы хотите это GetIndexParameters() метод. Если массив, который он возвращает, имеет более чем 0 элементов, это означает, что оно является индексированным свойством.

Для получения более подробной информации см. the MSDN documentation.

20

Извините, но

public string[] Items { get; set; } 

является не индексированных собственности, это просто типа массива! Однако следующее является:

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

Хорошо, но как вы находите это через отражение? – BrainSlugs83 2014-03-07 03:30:13

1

Вот код, который работал для меня:

 
foreach (PropertyInfo property in obj.GetType().GetProperties()) 
{ 
    object value = property.GetValue(obj, null); 
    if (value is object[]) 
    { 
    .... 
    } 
} 

P.S. .GetIndexParameters().Length > 0) работает для случая, описанного в этой статье: http://msdn.microsoft.com/en-us/library/b05d59ty.aspx Так что если вы заботитесь о свойстве Chars для значения типа string, используйте его, но он не работает для большинства интересующих вас массивов, в том числе, я довольно уверен, массив строк из исходного вопроса.

2

Если вы вызываете property.GetValue(obj,null), а свойство IS проиндексировано, вы получите исключение несоответствия счетчика параметров. Лучше проверить, индексируется ли свойство с помощью GetIndexParameters(), а затем решить, что делать.

0

Вы можете преобразовать индексатор 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); 
    } 
Смежные вопросы