List <dynamic>元素有字段但我无法访问它们。为什么呢?

时间:2015-05-12 10:16:31

标签: c# expandoobject

我需要遍历List<dynamic>个对象。

列表的对象都有值,但由于某种原因,我无法访问任何动态对象字段。下面是我的调试窗口的屏幕截图:

enter image description here

在那里你可以看到对象包含字段(例如别名 Id 名称等)。

我尝试将其投射到IDictionary<string, object>ExpandoObject,但无济于事。我之前没有遇到过这样的事情:无法访问dynamic对象中的现有字段

这里有什么问题?

代码正在抛出Microsoft.CSharp.RuntimeBinder.RuntimeBinderException,其中包含一条消息,指出{"'object' does not contain a definition for 'Name'"}.

创建列表时添加了匿名类型的对象,如下所示:

return new List<dynamic>(fields.Select(field => new 
                        { 
                            Id = field.Id, 
                            Alias = field.Alias, 
                            Name = field.Name, 
                            Type = field.Type, 
                            Value = field.Value,
                            SortOrder = field.SortOrder
                        }));

其中fieldsICollection<Field>,强类型集合。

1 个答案:

答案 0 :(得分:10)

有说服力的部分是例外:

  

{&#34;&#39;对象&#39;不包含&#39;名称&#39;}的定义。

这表明运行时活页夹实际上无法访问您在dynamic中传递的类型(因为dynamic确实实施了可见性规则)。

最可能的原因是你在一个不同的程序集中创建匿名类型,而不是随后读取它 - 因为匿名类型被声明为internal,这就消耗了程序集无法访问它,导致上面的错误消息。

与运行时绑定程序异常的常见情况对比:

  

&#39;&LT;&GT; f__AnonymousType0&LT;字符串&gt;&#39;不包含&#39;名称&#39;

的定义

修改

问题的一个可能解决方案是在包含匿名类型的程序集上使用InternalsVisibleToAttribute。但是,这是代码味道 - 就像InternalsVisibleToAttributeinternal本身的任何其他用法一样。

更好的方法是确保你没有实际通过集合边界传递匿名类型 - 毕竟,它们甚至不应该在它们来自的方法之外使用;事实上它们基本上是.NET的实现细节 - 他们没有其他方法来做同样的事情。这个可能会在未来的版本中进行更改,使InternalsVisibleToAttribute解决方案倍加不可靠。

您的代码使用dynamic的方式表明您的团队对dynamic如何工作以及如何使用它有错误的假设。请注意List<dynamic>的实际运行时类型实际上是List<object>。类型dynamic的参数也是如此(它们只是object,尽管标有DynamicAttribute)。事实上,这真的是dynamic - 它是处理运行时动态调度的一种方式 - 它不是类型或任何东西的属性,它&# 39; s就像你实际上调用你试图调用的那样。对于C#,dynamic允许您在使用这些动态类型时跳过大多数编译器检查,并生成一些代码来自动处理调度,但所有这些只发生在您实际使用的方法中dynamic关键字 - 如果您使用List<object>,则最终结果将完全相同。

在您的代码中,没有理由不使用简单的静态类型。除了努力编写类型本身之外,动态类型并没有给你带来任何好处。如果您的同事不喜欢这样,那么他们应该提供更好的解决方案 - 问题非常明显,而且您需要来处理这些问题。

更糟糕的是,它明确隐藏所有上下文所有类型信息。这不是你想要的API,内部与否!如果要隐藏正在使用的具体类型,为什么不 - 但是您仍然应该公开接口。我怀疑这就是为什么匿名类型无法实现接口的原因 - 它会鼓励你完全走错路。