DynamicObject?以下代码如何工作?

Lim*_*ing 1 c#

我似乎无法在MVC Webgrid的源代码中将以下代码拼凑在一起.

当我们构建网格列时,我们会说

grid.Column("Id", format: (item) => item.GetSelectLink(item.Id)),
Run Code Online (Sandbox Code Playgroud)

"item"显然是一个lambda参数,它实际上是一个"WebGridRow"类.(我认为!!除非我错了)在这里查看源代码

https://github.com/mono/aspnetwebstack/blob/master/src/System.Web.Helpers/WebGrid/WebGridRow.cs

我的问题是,"Id"不是这个类的属性,并且由于WebGridRow继承自DynamicObject,".Id"属性究竟是如何映射到当前行的"源对象"的?

顺便说一下,源对象"对象值"通过WebGridRow的构造函数传递

public WebGridRow(WebGrid webGrid, object value, int rowIndex)
{
    _grid = webGrid;
    _value = value;
    _rowIndex = rowIndex;
    _dynamic = value as IDynamicMetaObjectProvider;
}
Run Code Online (Sandbox Code Playgroud)

列定义

public Func<dynamic, object> Format { get; set; }
Run Code Online (Sandbox Code Playgroud)

列在"WeBGridRenderer"类中调用为

 foreach (var row in webGrid.Rows)
 {
                     .....
                    foreach (var column in columns)
                    {
                        var value = ...Format(column.Format, row).ToString();
                        ...
                    }
 }
Run Code Online (Sandbox Code Playgroud)

最后,"WeBGridRenderer"中的"格式"函数

private static HelperResult Format(Func<dynamic, object> format, dynamic arg) {
        var result = format(arg);
        ....
}
Run Code Online (Sandbox Code Playgroud)

Alx*_*ndr 6

[编辑]
我在这里写了一篇关于这个主题的相当广泛的博客文章:http://blog.alxandr.me/2013/07/26/dynamic-dispatch-how-dynamic-work-in-c/ 如果您对C#中的动态调度如何工作感兴趣,这可能会解释得相当多.
[/编辑]

我在DLR上做了很多工作,这是一个庞大而复杂的野兽,但我会尽量保持这一点.

使用dynamicC#执行任何操作时会发生什么,编译器会生成动态调用站点.如果你反编译代码,你最终会得到像CallSite<Func<CallSite, object, object, object>>大多数情况下的东西(不是函数,它们往往有2个以上的参数).调用站点做了很多魔术,我们不需要太多,但当一个对象实现IDynamicMetaObjectProvider动态调用站点(或使用的绑定器)时调用GetMetaObject(http://msdn.microsoft.com/en-所述对象上的us/library/system.dynamic.idynamicmetaobjectprovider.getmetaobject.aspx).

一个DynamicMetaObject角色是描述如何对给定对象执行动态操作.在您的情况下,动态操作是"读取属性名为Id",因此调用点调用BindGetMember动态元对象.这BindGetMember可以做任何它喜欢的,但是,在案件的DynamicObject它调用TryGetMemberDynamicObject本身.

现在,涉及到很多缓存(和黑魔法),这使得效率提高,并DynamicObject提供了一种简单的实现方式IDynamicMetaObjectProvider(有时可以成为一个真正的野兽),但这并不意味着每个dynamic对象是一个DynamicObject.

例如,如果我这样做:

dynamic test = "test";
int length = test.Length;
Run Code Online (Sandbox Code Playgroud)

test(显然是一个字符串)没有方法TryGetMember.然而,CSharpGetMemberBinder知道如何使用反射来确定string具有名为的属性Length并返回该属性.