2012-08-31 25 views
2

我有一個DynamicObject,我希望它可以轉換爲IDictionary,與ExpandoObject完全一樣。例如,鑄造ExpandoObject到IDictionary的是完全合法:爲什麼我不能在隱式轉換時返回接口,但是ExpandoObject可以嗎?

dynamic ex = new ExpandoObject(); 
ex.Field = "Foobar"; 
IDictionary<string, object> dict = ex as IDictionary<string, object>; 
Console.WriteLine (dict["Field"]); 

現在我儘量落實到我自己的DynamicObject這樣的:

public class MyDynamicObject : DynamicObject 
{ 
    public Dictionary<string, object> members = new Dictionary<string, object>(); 

    public override bool TryGetMember (GetMemberBinder binder, out object result) 
    { 
     if (members.ContainsKey (binder.Name)) { 
      result = members[binder.Name]; 
      return true; 
     } 
     else { 
      result = null; 
      return false; 
     } 
    } 
    public override bool TrySetMember (SetMemberBinder binder, object value) 
    { 
     this.members.Add (binder.Name, value); 
     return true; 
    } 
    public static implicit operator IDictionary<string, object> (MyDynamicObject mydo) 
    { 
     return (IDictionary<string, object>) mydo.members; 
    } 
} 

但是,編譯器將無法在public static implicit operator IDictionary<string, object>線,給人錯誤:「不能轉換爲或從一個接口類型」。如果我將隱式運算符更改爲Dictionary,則可以將MyDynamicObject強制轉換爲沒有任何問題的Dictionary,但不是IDictionary。

ExpandoObject如何做到這一點?

回答

8

ExpandoObject簡單實現IDictionary<string, object>

如果您想要具有相同的行爲,則還需要實施此接口並將所有呼叫委託給您的members字段。

事情是這樣的:

public class MyDynamicObject : DynamicObject, IDictionary<string, object> 
{ 
    public Dictionary<string, object> members = new Dictionary<string, object>(); 

    public IEnumerator<KeyValuePair<string, object>> GetEnumerator() 
    { 
     return members.GetEnumerator(); 
    } 

    public void Add(KeyValuePair<string, object> item) 
    { 
     members.Add(item.Key, item.Value); 
    } 

    // ... 
} 
+0

對於OP--你所需要做的就是:做到這一點,即'public class MyDynamicObject:DynamicObject,IDictionary '並填寫缺少的方法 –

+0

感謝您的快速響應!你的回答很有道理。不過,我將只需添加Dictionary 並將其轉換爲Dictionary,這足以滿足我的項目需求。 – Dyna

+1

使用ReSharper,此任務在2分鐘內通過「委派成員」選項完成。 –

0

轉換操作符不被DLR審問 - 因此這將無法工作。

您可以繼承IDictionary或者您可以覆蓋TryConvert方法。

自從實施IDictionary需要一個實現或鉗出大量的操作,還有,你可能會發現TryConvert航線實際上是更容易實現;缺點是在你實現TryConvert時,你幾乎可以肯定會在你每次調用它時產生一個字典的新實例(除非你緩存結果保持最新狀態),因此可能需要額外的性能提升

0

它在C#規範中定義:

A class or struct is permitted to declare a conversion from a source type S to a target type T provided all of the following are true:

  • ...
  • Neither S nor T is object or an interface-type.

this Stack Overflow答案。

相關問題