Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 列表<;动态>;元素有字段,但我无法访问它们。为什么?_C#_Expandoobject - Fatal编程技术网

C# 列表<;动态>;元素有字段,但我无法访问它们。为什么?

C# 列表<;动态>;元素有字段,但我无法访问它们。为什么?,c#,expandoobject,C#,Expandoobject,我需要循环查看列表对象 列表的对象都有值,但由于某种原因,我无法访问任何动态对象字段。下面是我的调试窗口的屏幕截图: 在那里可以看到对象包含字段(如别名、Id、名称等) 我尝试将其强制转换为IDictionary和ExpandoObject,但都没有成功。我以前没有遇到过这样的情况:当动态对象中的现有字段存在时,无法访问它们 这里怎么了 代码正在抛出一个Microsoft.CSharp.RuntimeBinder.RuntimeBinderException,其中有一条消息说明{“'objec

我需要循环查看
列表
对象

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

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

我尝试将其强制转换为
IDictionary
ExpandoObject
,但都没有成功。我以前没有遇到过这样的情况:当
动态对象中的现有字段存在时,无法访问它们

这里怎么了

代码正在抛出一个
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
,其中有一条消息说明
{“'object'不包含'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
                        }));
返回新列表(字段)。选择(字段=>new
{ 
Id=字段.Id,
别名=字段。别名,
Name=field.Name,
Type=field.Type,
Value=field.Value,
SortOrder=field.SortOrder
}));

其中,
字段
是一个
i集合
,一个强类型集合。

说明部分是例外:

{“对象”不包含“名称”的定义}

这表明运行时绑定器实际上无法访问您传入的类型
dynamic
(因为
dynamic
实际上强制执行可见性规则)

最有可能的原因是您在不同的程序集中创建的匿名类型与您随后读取它的程序集中创建的匿名类型不同-由于匿名类型声明为
internal
,因此使用程序集无法访问它,从而导致上面的错误消息

与运行时绑定器异常的常见情况相比:

“f__AnonymousType0”不包含“名称”的定义

编辑:

该问题的一个可能解决方案是在包含匿名类型的程序集上使用
内部visibletoAttribute
。然而,这就是代码气味——就像
InternalsVisibleToAttribute
internal
本身的任何其他用法一样

一个更好的方法是确保您实际上不会通过程序集边界传递匿名类型——毕竟,它们甚至不应该在它们起源的方法之外使用;事实上,它们基本上是.NET的一个实现细节——它们没有其他方法来做同样的事情。这可能会在未来的版本中发生变化,从而使
内部可视属性
解决方案更加不可靠

您的代码使用
dynamic
的方式表明,您的团队对
dynamic
的工作原理和使用方法的假设存在缺陷。注意
List
的实际运行时类型实际上是如何
List
。类型为
dynamic
的参数也是如此(它们同样只是
对象
,尽管标记为
DynamicAttribute
)。事实上,这就是
dynamic
的真正含义-它是一种处理运行时动态调度的方法-它不是该类型的属性或任何东西,它只是您实际调用您试图调用的任何东西的方式。对于C#,
dynamic
允许您在处理这些动态类型时跳过大多数编译器检查,并生成一些代码来自动处理分派,但所有这些都只发生在实际使用
dynamic
关键字的方法内部-如果使用
List
,最终结果将完全相同

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


更糟糕的是,它显式隐藏了所有上下文和所有类型信息。这不是你想要的API,不管是内部的还是非内部的!如果您想隐藏正在使用的具体类型,为什么不呢?但是您仍然应该公开一个接口。我怀疑这就是匿名类型无法实现接口的原因——这会鼓励您完全走错方向。

这会导致异常,还是只会导致空白字段?此外,发布您的代码也会很有用。@ChrisMantle:我不认为添加更多源代码有什么价值。让我们假设我从一个未知的来源得到这个,重要的是,正如屏幕截图所示,列表中的一个给定元素有字段。问题是:如何访问它们?是的,我确实收到了Microsoft.CSharp.RuntimeBinder.RuntimeBinderException。请阅读。
部分.Fields中的值是动态/匿名的,还是不同类型的静态类型?@Veverke仅用于测试,因为您编写的内容似乎没有问题,应该确实可以工作。将Name属性更改为Test i wan,以查看是否会显示异常:{“'object'不包含'Test'”的定义}。此外,您的错误消息
{“'object'不包含'Name'”的定义}
很奇怪。通常,它会说一些类似的话
{“f_AnonymousType0”不包含“Name”的定义}
感谢David Arno以及Jon Skeet提到这一点。我的第一次检查做得很差。@Veverke这几乎肯定是错误的解决方案。这些类型是内部的是有原因的。它们的设计目的不是在创建它们的方法的范围之外使用。你花了很多精力来解决这个问题。只需为您的查询创建新的命名类型