今天在研究C#动态时,有些东西让我感到惊讶(我从未使用过它们,但最近我一直在尝试使用Nancy Web框架)。我发现我不能这样做:
dynamic expando = new ExpandoObject();
expando.name = "John";
Console.WriteLine(expando["name"]);
最后一行抛出异常:
无法将带有[]的索引应用于类型的表达式 'System.Dynamic.ExpandoObject'
我理解错误信息,但我不明白为什么会这样。我查看了ExpandoObject的文档,它显式实现了IDictionary<,>
,因此有一个this.[index]
方法(MSDN)。为什么我不能打电话给它?
当然,没有什么可以阻止我手动将ExpandoObject
向下转换为字典,然后将其编入索引,但这种情况无视这一点;它也没有解释Expando如何能够隐藏其中一个接口的方法。
这里发生了什么?
答案 0 :(得分:44)
Expando如何能够隐藏其中一个接口的方法。
正如您在文档中正确发现的那样,indexer is和explicit interface implementation。来自Explicit Interface Implementation Tutorial:
实现接口的类可以显式实现该接口的成员。显式实现成员时,不能通过类实例访问它,而只能通过接口的实例访问它。
这意味着您必须将引用转换为接口才能访问它:
((IDictionary<String, Object>)expando)["name"]
答案 1 :(得分:2)
使用此工厂类创建ExpandoObjects!然后使用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;
}
}