首先是错误信息
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:'System.Collections.Generic.List'在System.Dynamic.UpdateDelegates.UpdateAndExecute1(CallSite站点,T0)的CallSite.Target(Closure,CallSite,Object)中不包含'First'的定义. arg0)在ToPropertyDictionaryTests.cs中的ClaySharp.Tests.ToPropertyDictionaryTests.TestExpando():第91行
测试:
[测试]
public void TestExpando()
{
dynamic root = new ExpandoObject();
root.Name = "Name";
var result = GetExpandos();
root.Child = result;
var first = root.Child.First();
Assert.That(first.Name, Is.EqualTo("Obj1"));
}
private IEnumerable<dynamic> GetExpandos()
{
var toReturn = new List<dynamic>();
dynamic obj1 = new ExpandoObject();
toReturn.Add(obj1);
obj1.Name = "Obj1";
dynamic obj2 = new ExpandoObject();
toReturn.Add(obj2);
obj2.Name = "Obj2";
return toReturn;
}
Run Code Online (Sandbox Code Playgroud)
有趣的是,如果从图片中删除"root",并且对"结果"执行测试而不是正常工作.
现在对于非常奇怪的部分.在返回"toReturn"之前调试是设定点.看看这个,它的确有效
?toReturn.GetType().全名
"System.Collections.Generic.List`1 [[System.Object,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089]]"
?回来
Count = 2 [0]:{System.Dynamic.ExpandoObject} [1]:{System.Dynamic.ExpandoObject}
?toReturn.First()
{} System.Dynamic.ExpandoObject
就在它被分配到"root"之前,仍然有效
?结果
Count = 2 [0]:{System.Dynamic.ExpandoObject} [1]:{System.Dynamic.ExpandoObject}
?result.First()
{} System.Dynamic.ExpandoObject
但在将其分配给root后,此操作将失败
?root.Child
{System.Collections.Generic.List} [0]:{System.Dynamic.ExpandoObject} [1]:{System.Dynamic.ExpandoObject}
?root.Child.First()
dynamic目前不适用于扩展方法; First当"作为"扩展方法调用时,编译器将无法在运行时"动态"绑定到LINQ to Objects 方法.从语言规范:
7.6.5.2扩展方法调用
...如果调用的正常处理找不到适用的方法,则尝试将构造作为扩展方法调用进行处理.如果expr或任何args具有编译时类型dynamic,则扩展方法将不适用.
要了解原因,您可能希望阅读C#4中的动态关键字是否支持扩展方法?
更换:
var first = root.Child.First();
Run Code Online (Sandbox Code Playgroud)
显式调用静态方法:
var first = Enumerable.First(root.Child);
Run Code Online (Sandbox Code Playgroud)
或者只是使用索引器:
var first = root.Child[0];
Run Code Online (Sandbox Code Playgroud)
编辑:
有趣的是,如果从图片中删除"root",并且对"结果"执行测试而不是正常工作.
该变量result隐式输入IEnumerable<dynamic>; 这是它的编译时(静态)类型.在这种情况下,当您这样做时result.First(),编译器Enumerable.First在编译时绑定到该方法没有问题.如果您将编译时类型更改result为dynamic,则错误将重复出现.