ExpandoObject - 为什么类型的行为不同?
ExpandoObject - why a Type behaves differently?
一个给大师,请说服me/us这是怎么回事。
List<ExpandoObject> peopleList = new List<ExpandoObject>();
dynamic expandoObj1 = new ExpandoObject();
expandoObj1.id = 1;
expandoObj1.first = "fred";
expandoObj1.last = "krugger";
peopleList.Add(expandoObj1);
dynamic expandoObj2 = new ExpandoObject();
expandoObj2.id = 2;
expandoObj2.first = "george";
expandoObj2.last = "benson";
peopleList.Add(expandoObj2);
//test access the props
var expObj = expandoObj1;
var name = expObj.first;
var expObj2 = peopleList[0] as dynamic;
var name2 = expObj2.first;
IDictionary<string, object> expObj3 = peopleList[0] as ExpandoObject;
var name3 = expObj3["first"];
var expObj4 = peopleList[0] as ExpandoObject;
//var name4 = expObj4.first; //THIS DOESN'T WORK - ExpandoObject does not contain a definition for 'first' etc...
在所有情况下,LEFT-HAND SIDE 都是 System.Dynamic.ExpandoObject;
那么,为什么在第 4 个案例 expObj4 中,我无法访问 属性 expObj4.first?
这是因为变量 expObj4
被声明为 ExpandoObject
而不是 dynamic
。这是一个重要的区别。
试试这个:
dynamic a = new ExpandoObject();
a.Name = "Test";
这个可以编译,但下面的不能:
ExpandoObject a = new ExpandoObject();
a.Name = "Test";
你明白了:
CS1061 'ExpandoObject' does not contain a definition for 'Name' and no extension method 'Name' accepting a first argument of type 'ExpandoObject' could be found
您拥有的与此相关的变量是:
- expandoObj1 - 动态
- expandoObj2 - 动态
- expObj1 - 动态
- expObj2 - 动态
- expObj3 - 字典,但是你在这里使用字典访问,而不是点访问
编译器的神奇 "let's see if we can access the thing at runtime" 代码仅在表达式或变量为 dynamic
时才会启动。 ExpandoObject
只是支持这个的类型
ExpandoObject 是一个密封的 class,它将数据存储在字典中。它实现 IDynamicMetaObjectProvider 接口,该接口为实现它的 classes 提供动态行为。它还实现了 IDictionary 接口,该接口为其提供类似字典的行为。它应该在编译时进行检查和验证。
dynamic 是一种编译器不应在编译时检查的类型。它在运行时被检查和中断。在编译时,假定动态实体支持任何操作。因此,当您说它是一个 expandoobject 时,首先调用的字段不会附加到对象本身。
在这里检查 expando 对象的源代码
将动态行为想象成一个对象。你可以把任何类型放在那里。当您添加到列表时,您是以动态方式添加到列表中的,但所添加项目的固有类型是 ExpandoObject。因此,您可以将其转换回 ExpandoObject。
当你说,
expandoObj1.first = "fred";
等于说,
expandoObj1.Add("first", "fred");
当你使用
var expObj = expandoObj1;
var name = expObj.first;
您使用的是动态形式的 expandoObject。因此,您可以直接访问属性。当您将其转换为 ExpandoObject class 时,您使用的是实际的 ExpandoObject class,它在字典中存储字段,因此点 (.) 符号不起作用。
var expObj4 = peopleList[0] as ExpandoObject;
左侧的变量仍然是 ExpandoObject,不是字典。 ExpandoObject 通过集合搜索公开其成员。
var name4 = expObj4.Where(t=>t.Key == "first").First().Value;
当您将其转换为字典时,它就像字典一样工作。
IDictionary<string, object> expObj3 = peopleList[0] as ExpandoObject;
var name3 = expObj3["first"];
当您将其转换为动态时,您可以访问这些键,就像它们是 class 的属性一样。
进一步参考
Dynamically adding properties to an ExpandoObject
一个给大师,请说服me/us这是怎么回事。
List<ExpandoObject> peopleList = new List<ExpandoObject>();
dynamic expandoObj1 = new ExpandoObject();
expandoObj1.id = 1;
expandoObj1.first = "fred";
expandoObj1.last = "krugger";
peopleList.Add(expandoObj1);
dynamic expandoObj2 = new ExpandoObject();
expandoObj2.id = 2;
expandoObj2.first = "george";
expandoObj2.last = "benson";
peopleList.Add(expandoObj2);
//test access the props
var expObj = expandoObj1;
var name = expObj.first;
var expObj2 = peopleList[0] as dynamic;
var name2 = expObj2.first;
IDictionary<string, object> expObj3 = peopleList[0] as ExpandoObject;
var name3 = expObj3["first"];
var expObj4 = peopleList[0] as ExpandoObject;
//var name4 = expObj4.first; //THIS DOESN'T WORK - ExpandoObject does not contain a definition for 'first' etc...
在所有情况下,LEFT-HAND SIDE 都是 System.Dynamic.ExpandoObject; 那么,为什么在第 4 个案例 expObj4 中,我无法访问 属性 expObj4.first?
这是因为变量 expObj4
被声明为 ExpandoObject
而不是 dynamic
。这是一个重要的区别。
试试这个:
dynamic a = new ExpandoObject();
a.Name = "Test";
这个可以编译,但下面的不能:
ExpandoObject a = new ExpandoObject();
a.Name = "Test";
你明白了:
CS1061 'ExpandoObject' does not contain a definition for 'Name' and no extension method 'Name' accepting a first argument of type 'ExpandoObject' could be found
您拥有的与此相关的变量是:
- expandoObj1 - 动态
- expandoObj2 - 动态
- expObj1 - 动态
- expObj2 - 动态
- expObj3 - 字典,但是你在这里使用字典访问,而不是点访问
编译器的神奇 "let's see if we can access the thing at runtime" 代码仅在表达式或变量为 dynamic
时才会启动。 ExpandoObject
只是支持这个的类型
ExpandoObject 是一个密封的 class,它将数据存储在字典中。它实现 IDynamicMetaObjectProvider 接口,该接口为实现它的 classes 提供动态行为。它还实现了 IDictionary 接口,该接口为其提供类似字典的行为。它应该在编译时进行检查和验证。
dynamic 是一种编译器不应在编译时检查的类型。它在运行时被检查和中断。在编译时,假定动态实体支持任何操作。因此,当您说它是一个 expandoobject 时,首先调用的字段不会附加到对象本身。
在这里检查 expando 对象的源代码
将动态行为想象成一个对象。你可以把任何类型放在那里。当您添加到列表时,您是以动态方式添加到列表中的,但所添加项目的固有类型是 ExpandoObject。因此,您可以将其转换回 ExpandoObject。
当你说,
expandoObj1.first = "fred";
等于说,
expandoObj1.Add("first", "fred");
当你使用
var expObj = expandoObj1;
var name = expObj.first;
您使用的是动态形式的 expandoObject。因此,您可以直接访问属性。当您将其转换为 ExpandoObject class 时,您使用的是实际的 ExpandoObject class,它在字典中存储字段,因此点 (.) 符号不起作用。
var expObj4 = peopleList[0] as ExpandoObject;
左侧的变量仍然是 ExpandoObject,不是字典。 ExpandoObject 通过集合搜索公开其成员。
var name4 = expObj4.Where(t=>t.Key == "first").First().Value;
当您将其转换为字典时,它就像字典一样工作。
IDictionary<string, object> expObj3 = peopleList[0] as ExpandoObject;
var name3 = expObj3["first"];
当您将其转换为动态时,您可以访问这些键,就像它们是 class 的属性一样。
进一步参考 Dynamically adding properties to an ExpandoObject