2009-05-12 37 views
7

Tôi có một cá thể thực hiện IDictionary<T, K>, tôi không biết T và K ở thời gian cộng tác và muốn nhận tất cả các phần tử từ đó. Tôi không muốn sử dụng IEnumerable vì một số lý do, đó sẽ là giao diện không chung chung duy nhất được triển khai bởi IDictionary.Lấy các giá trị của một IDictionary chung bằng cách sử dụng sự phản chiếu

Mã tôi có cho đến nay:

// getting types 
Type iDictType = instance.GetType().GetInterface("IDictionary`2"); 
Type keyType = iDictType.GetGenericArguments()[0]; 
Type valueType = iDictType.GetGenericArguments()[1]; 

// getting the keys 
IEnumerable keys = (IEnumerable)dictType.GetProperty("Keys") 
    .GetValue(instance, null); 

foreach (object key in keys) 
{ 
    // ==> this does not work: calling the [] operator 
    object value = dictType.GetProperty("Item") 
    .GetValue(instance, new object[] {key }); 


    // getting the value from another instance with TryGet 
    MethodInfo tryGetValue = iDictType.GetMethod("TryGetValue"); 
    object[] arguments = new object[] { key, null }; 
    bool hasElement = (bool)tryGetValue.Invoke(otherInstance, arguments); 
    object anotherValue = arguments[1]; 
} 

tôi cũng có thể gọi TryGetValue, nhưng tôi nghĩ chúng ta có thể gọi toán tử []. Ai có thể giúp tôi?

+0

Tôi không chắc chắn rằng tôi hiểu câu hỏi. Bạn có muốn sử dụng toán tử [] thay vì nhận giá trị của thuộc tính Item thông qua Reflection không? – Andy

+0

Đã thử điều này với từ điển và cố gắng sử dụng trình lập chỉ mục/get_Item hoạt động cho tôi. – Gishu

+0

@Andy: Toán tử [] thực sự gọi một thuộc tính Item ở thời gian chạy, không hiển thị tại thời gian biên dịch. @Gishu: bạn gọi cho trình chỉ mục như thế nào? Không có thuộc tính 'Item', chỉ có phương thức 'get_Item'? –

Trả lời

21

Nó sẽ là tốt hơn để hình ra các TKey/TValue, và chuyển đổi thành mã thường xuyên qua MakeGenericMethod - như vậy:

(chỉnh sửa - bạn có thể vượt qua trong otherInstance như một cuộc tranh cãi quá, nếu họ là cùng loại)

static class Program 
{ 
    static void Main() 
    { 
     object obj = new Dictionary<int, string> { 
      { 123, "abc" }, { 456, "def" } }; 

     foreach (Type iType in obj.GetType().GetInterfaces()) 
     { 
      if (iType.IsGenericType && iType.GetGenericTypeDefinition() 
       == typeof(IDictionary<,>)) 
      { 
       typeof(Program).GetMethod("ShowContents") 
        .MakeGenericMethod(iType.GetGenericArguments()) 
        .Invoke(null, new object[] { obj }); 
       break; 
      } 
     } 
    } 
    public static void ShowContents<TKey, TValue>(
     IDictionary<TKey, TValue> data) 
    { 
     foreach (var pair in data) 
     { 
      Console.WriteLine(pair.Key + " = " + pair.Value); 
     } 
    }  
} 
+0

Ahh, tôi chưa bao giờ thấy rằng hashtable initializer trước đây! +1 – leppie

+0

@Leppie - nó là một phần của cú pháp khởi tạo bộ sưu tập; bạn có thể sử dụng bất kỳ phương thức Thêm nào, nhưng nếu phải mất nhiều đối số, bạn sẽ kết hợp với một bộ dấu ngoặc bổ sung. Vì vậy, {123, "abc"} cuộc gọi .Thêm (123, "abc") –

+0

Rất đẹp. Có một vấn đề: iType.GetGenericArguments() có thể thất bại, vì bản thân loại bê tông không cần phải có cùng các đối số chung như IDictionary nó thực hiện. Nhưng tôi có mã để có được đúng loại đã có trong câu hỏi. –

4

Chỉ cần hoàn thành, thậm chí nếu giải pháp Marc Gravell là đẹp hơn nhiều, đây là cách làm thế nào nó hoạt động theo cách tôi đã bắt đầu:

object value = dictType.GetMethod("get_Item") 
    .Invoke(instance, new object[] { key }); 

Điều này gọi toán tử [] của từ điển.

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