2008-11-14 27 views
22

Tôi đang viết một phương pháp Clone sử dụng sự phản chiếu. Làm thế nào để phát hiện ra một thuộc tính là một thuộc tính được lập chỉ mục sử dụng sự phản chiếu? Ví dụ:C# Reflection Indexed Properties

public string[] Items 
{ 
    get; 
    set; 
} 

Phương pháp của tôi cho đến nay:

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

Đó không phải là một tài sản được lập chỉ mục, đó là một tài sản mà trả về một mảng. –

+3

Câu hỏi này cần được thay đổi bởi người kiểm duyệt. Đây là kết quả google hàng đầu cho việc tìm kiếm một thuộc tính indexer nhưng đó không phải là ví dụ mã minh họa. Một nửa câu trả lời dưới đây trả lời câu hỏi và một nửa ví dụ về mã. –

Trả lời

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

Những gì bạn muốn là phương pháp GetIndexParameters(). Nếu mảng mà nó trả về có nhiều hơn 0 mục, điều đó có nghĩa đó là một thuộc tính được lập chỉ mục.

Xem the MSDN documentation để biết thêm chi tiết.

20

Xin lỗi, nhưng

public string[] Items { get; set; } 

không một tài sản được lập chỉ mục, nó chỉ đơn thuần là một loại mảng! Tuy nhiên sau đây là:

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

Được rồi, nhưng làm thế nào để bạn tìm thấy nó thông qua sự phản ánh? – BrainSlugs83

1

Dưới đây là một số mã mà làm việc cho tôi:

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

T.B. .GetIndexParameters().Length > 0) hoạt động cho trường hợp được mô tả trong bài viết này: http://msdn.microsoft.com/en-us/library/b05d59ty.aspx Vì vậy, nếu bạn quan tâm đến thuộc tính có tên Chars cho một giá trị kiểu chuỗi, hãy sử dụng nó, nhưng nó không hoạt động cho hầu hết các mảng mà tôi quan tâm, bao gồm, tôi khá chắc chắn, một mảng chuỗi từ câu hỏi ban đầu.

2

Nếu bạn gọi property.GetValue(obj,null) và thuộc tính IS được lập chỉ mục, khi đó bạn sẽ nhận được thông số ngoại lệ không khớp. Tốt hơn là kiểm tra xem thuộc tính có được lập chỉ mục bằng cách sử dụng GetIndexParameters() và sau đó quyết định việc cần làm.

0

Bạn có thể chuyển đổi các indexer để 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); 
    } 
+0

Tôi nghĩ rằng điều này chỉ xử lý các thuộc tính chỉ số nguyên-chỉ mục, đúng không? không có chỉ mục dựa trên chuỗi, không có tham số chỉ mục nhiều ... hoặc tôi có thiếu gì đó không? –

+0

@CodeJockey - Bạn có thể đúng; Tôi gặp sự cố khi làm cho nó hoạt động với kiểu đầu vào 'Chuỗi'. Nó đang treo trên thuộc tính được lập chỉ mục 'Chars'. Trừ khi tôi đang thiếu một cái gì đó bản thân mình ... – InteXX

Các vấn đề liên quan