2012-08-31 20 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答案。

相关问题