【问题标题】:Why can't I return an Interface on implicit casting, but ExpandoObject can?为什么我不能在隐式转换中返回接口,但 ExpandoObject 可以?
【发布时间】:2012-08-31 07:51:21
【问题描述】:

我有一个DynamicObject,我希望它可以转换为 IDictionary,与ExpandoObject 完全相同。例如,将 ExpandoObject 强制转换为 IDictionary 是完全有效的:

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&lt;string, object&gt;line 上失败,给出错误:“无法转换为接口类型或从接口类型转换”。如果我将隐式运算符更改为 Dictionary,我可以将 MyDynamicObject 转换为 Dictionary 而不会出现任何问题,但不是 IDictionary。

ExpandoObject 如何做到这一点?

【问题讨论】:

    标签: c# dynamic interface casting expandoobject


    【解决方案1】:

    ExpandoObject 简单地实现了IDictionary&lt;string, object&gt;

    如果您想拥有相同的行为,您还需要实现此接口并将所有调用委托给您的 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);
        }
    
        // ...
    }
    

    【讨论】:

    • 对于 OP - 您需要做的就是:也这样做,即public class MyDynamicObject : DynamicObject, IDictionary&lt;string, object&gt; 并填写缺少的方法
    • 感谢您的快速回复!你的回答很有道理。但是,我将只添加 Dictionary 并转换为 Dictionary,这对我的项目来说已经足够了。
    • 使用 ReSharper,此任务通过“委派成员”选项在 2 分钟内完成。
    【解决方案2】:

    DLR 不会询问演员表操作员 - 因此这不起作用。

    您可以从IDictionary 继承,也可以覆盖TryConvert 方法。

    由于实现IDictionary 还需要实现或存根大量操作,您可能会发现TryConvert 路由实际上更容易实现;缺点是在您的TryConvert 的实现中,您几乎肯定会在每次调用它时生成一个新的字典实例(除非您缓存结果保持最新)所以它可能获得额外的性能冲击

    【讨论】:

      【解决方案3】:

      在 C# 规范中定义:

      一个类或结构被允许 从源声明转换 类型 S 到目标类型 T 提供所有 以下是正确的:

      • ...
      • S 和 T 都不是object接口类型

      请参阅this Stack Overflow 答案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-17
        • 1970-01-01
        • 2012-07-18
        • 1970-01-01
        • 2016-07-03
        • 1970-01-01
        • 2014-07-31
        • 1970-01-01
        相关资源
        最近更新 更多