简体   繁体   English

为什么我不能索引到 ExpandoObject?

[英]Why can't I index into an ExpandoObject?

Something caught me by surprise when looking into C# dynamics today (I've never used them much, but lately I've been experimenting with the Nancy web framework).今天在研究 C# 动态时,有些让我吃惊(我从来没有经常使用它们,但最近我一直在试验 Nancy Web 框架)。 I found that I couldn't do this:我发现我不能这样做:

dynamic expando = new ExpandoObject();

expando.name = "John";

Console.WriteLine(expando["name"]);

The last line throws an exception:最后一行抛出异常:

Cannot apply indexing with [] to an expression of type 'System.Dynamic.ExpandoObject'无法将 [] 索引应用于“System.Dynamic.ExpandoObject”类型的表达式

I understand the error message, but I don't understand why this is happening.我理解错误消息,但我不明白为什么会发生这种情况。 I have looked at the documentation for ExpandoObject and it explicitly implements IDictionary<,> and thus has a this.[index] method (MSDN ).我查看了 ExpandoObject 的文档,它明确地实现了IDictionary<,> ,因此有一个this.[index]方法(MSDN )。 Why can't I call it?为什么我不能调用它?

Of course, there's nothing to stop me from downcasting the ExpandoObject to a dictionary manually and then indexing into it, but that kind of defies the point;当然,没有什么可以阻止我手动将ExpandoObject向下转换为字典,然后对其进行索引,但这有点违背了这一点; it also doesn't explain how the Expando was able to hide the method of one of its interfaces.它也没有解释 Expando 如何能够隐藏其接口之一的方法。

What's going on here?这里发生了什么?

how the Expando was able to hide the method of one of its interfaces. Expando 如何能够隐藏其接口之一的方法。

Because as you correctly found out in the documentation, the indexer is an explicit interface implementation .因为正如您在文档中正确发现的那样, 索引器是一个显式接口实现 From Explicit Interface Implementation Tutorial :来自 显式接口实现教程

A class that implements an interface can explicitly implement a member of that interface.实现接口的类可以显式实现该接口的成员。 When a member is explicitly implemented, it cannot be accessed through a class instance, but only through an instance of the interface.显式实现成员时,不能通过类实例访问,只能通过接口实例访问。

This means you'll have to cast the reference to the interface to access it:这意味着您必须将引用转换为接口才能访问它:

((IDictionary<String, Object>)expando)["name"]

Use this factory class to create ExpandoObjects!使用这个工厂类来创建 ExpandoObjects! Then use HasProperty("prop name") or GetValue("prop name")然后使用 HasProperty("prop name") 或 GetValue("prop name")

void Main()
{
    dynamic _obj = ExpandoObjectFactory.Create();
    if (_obj.HasProperty("Foo") == false)
    {
        _obj.Foo = "Foo";
    }
    Console.WriteLine(_obj); // Foo;
    object bar = _obj.GetValue("Bar");
    Console.WriteLine(bar); // null
}

public static class ExpandoObjectFactory
{
    public static ExpandoObject Create()
    {
        dynamic expandoObject = new ExpandoObject();
        expandoObject.HasProperty = new Func<string, bool>((string name) => ((IDictionary<string, object>)expandoObject).ContainsKey(name));
        expandoObject.GetValue = new Func<string, object>(delegate (string name)
        {
            ((IDictionary<string, object>)expandoObject).TryGetValue(name, out object value);
            return value;
        });
        return expandoObject;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM