我需要遍历List<dynamic>
个对象。
列表的对象都有值,但由于某种原因,我无法访问任何动态对象字段。下面是我的调试窗口的屏幕截图:
在那里你可以看到对象包含字段(例如别名, 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
}));
其中fields
是ICollection<Field>
,强类型集合。
答案 0 :(得分:10)
有说服力的部分是例外:
{&#34;&#39;对象&#39;不包含&#39;名称&#39;}的定义。
这表明运行时活页夹实际上无法访问您在dynamic
中传递的类型(因为dynamic
确实实施了可见性规则)。
最可能的原因是你在一个不同的程序集中创建匿名类型,而不是随后读取它 - 因为匿名类型被声明为internal
,这就消耗了程序集无法访问它,导致上面的错误消息。
与运行时绑定程序异常的常见情况对比:
&#39;&LT;&GT; f__AnonymousType0&LT;字符串&gt;&#39;不包含&#39;名称&#39;
的定义
修改强>
问题的一个可能解决方案是在包含匿名类型的程序集上使用InternalsVisibleToAttribute
。但是,这是代码味道 - 就像InternalsVisibleToAttribute
或internal
本身的任何其他用法一样。
更好的方法是确保你没有实际通过集合边界传递匿名类型 - 毕竟,它们甚至不应该在它们来自的方法之外使用;事实上它们基本上是.NET的实现细节 - 他们没有其他方法来做同样的事情。这个可能会在未来的版本中进行更改,使InternalsVisibleToAttribute
解决方案倍加不可靠。
您的代码使用dynamic
的方式表明您的团队对dynamic
如何工作以及如何使用它有错误的假设。请注意List<dynamic>
的实际运行时类型实际上是List<object>
。类型dynamic
的参数也是如此(它们只是object
,尽管标有DynamicAttribute
)。事实上,这真的是dynamic
- 它是处理运行时动态调度的一种方式 - 它不是类型或任何东西的属性,它&# 39; s就像你实际上调用你试图调用的那样。对于C#,dynamic
允许您在使用这些动态类型时跳过大多数编译器检查,并生成一些代码来自动处理调度,但所有这些只发生在您实际使用的方法中dynamic
关键字 - 如果您使用List<object>
,则最终结果将完全相同。
在您的代码中,没有理由不使用简单的静态类型。除了努力编写类型本身之外,动态类型并没有给你带来任何好处。如果您的同事不喜欢这样,那么他们应该提供更好的解决方案 - 问题非常明显,而且您需要来处理这些问题。
更糟糕的是,它明确隐藏所有上下文,所有类型信息。这不是你想要的API,内部与否!如果要隐藏正在使用的具体类型,为什么不 - 但是您仍然应该公开接口。我怀疑这就是为什么匿名类型无法实现接口的原因 - 它会鼓励你完全走错路。