List 元素有字段但我无法访问它们。 为什么?
我需要遍历List
对象。
列表的对象都有值,但由于某种原因,我无法访问任何动态对象字段。 下面是我的调试窗口的屏幕截图:
在那里你可以看到对象包含字段(例如Alias , Id , Name等)。
我尝试将它转换为IDictionary
和ExpandoObject
,但无济于事。 我之前没有遇到过这样的事情: 当 dynamic
对象存在时无法访问现有字段。
这有什么不对?
该代码抛出一个Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
并显示一条消息,指出{"'object' does not contain a definition for 'Name'"}.
创建列表时添加了匿名类型的对象,如下所示:
return new List(fields.Select(field => new { Id = field.Id, Alias = field.Alias, Name = field.Name, Type = field.Type, Value = field.Value, SortOrder = field.SortOrder }));
其中fields
是ICollection
,一个强类型集合。
告诉部分是例外:
{“’object’不包含’Name’的定义”}。
这表明运行时绑定程序实际上无法访问您在dynamic
传递的类型(因为dynamic
实际上实际上强制执行可见性规则)。
最可能的原因是你在一个不同的程序集中创建匿名类型,而不是你随后读取它的那个 – 因为匿名类型被声明为internal
,消费程序集无法访问它,导致上面的错误消息。
与通常的运行时绑定程序exception情况相比:
‘<> f__AnonymousType0
‘不包含’Name’的定义
编辑:
该问题的可能解决方案是在包含匿名类型的程序集上使用InternalsVisibleToAttribute
。 然而,这是代码味道 – 就像任何其他使用InternalsVisibleToAttribute
或internal
本身一样。
更好的方法是确保你没有实际通过程序集边界传递匿名类型 – 毕竟,它们甚至不应该在它们源自的方法之外使用; 事实上它们基本上是.NET的实现细节 – 它们没有其他方法来做同样的事情。 这可能会在未来版本中发生变化,使InternalsVisibleToAttribute
解决方案变得双重不可靠。
您的代码使用dynamic
表明您的团队对dynamic
如何工作以及如何使用它有错误的假设。 请注意List
的实际运行时类型实际上是List
。 dynamic
类型的参数也是如此(它们只是object
,尽管标有DynamicAttribute
)。 事实上,这确实是dynamic
的 – 它是处理运行时动态调度的一种方式 – 它不是类型或任何东西的属性 ,它只是你实际调用你想要调用的任何东西的方式。 对于C#, dynamic
允许您在使用这些动态类型时跳过大多数编译器检查,并生成一些代码来自动处理调度,但所有这些只发生在您实际使用dynamic
关键字的方法中 -如果您使用List
,则最终结果将完全相同。
在您的代码中,没有理由不使用简单的静态类型。 除了为类型本身编写代码的努力之外,动态类型并没有真正给你带来任何好处。 如果你的同事不喜欢这样,那么他们应该提出一个更好的解决方案 – 问题非常明显,而且你需要处理这个问题。
更糟糕的是,它明确地隐藏了所有上下文 , 所有类型信息 。 这不是你想要的API,内部与否! 如果要隐藏正在使用的具体类型,为什么不 – 但是您仍然应该公开接口。 我怀疑这就是为什么匿名类型无法实现接口的原因 – 它会鼓励你完全走错路。