1

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

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

grid.Column("Id", format: (item) => item.GetSelectLink(item.Id)),

“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;
}

列定义

public Func<dynamic, object> Format { get; set; }

列在“WebGridRenderer”类中调用为

 foreach (var row in webGrid.Rows)
 {
                     .....
                    foreach (var column in columns)
                    {
                        var value = ...Format(column.Format, row).ToString();
                        ...
                    }
 }

最后是“WebGridRenderer”中的“Format”函数

private static HelperResult Format(Func<dynamic, object> format, dynamic arg) {
        var result = format(arg);
        ....
}
4

2 回答 2

6

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

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

当您dynamic在 C# 中使用 a 执行任何操作时,编译器会生成一个动态调用站点。如果你反编译代码,你最终会得到类似CallSite<Func<CallSite, object, object, object>>大多数情况下的东西(不是函数,它们往往有两个以上的参数)。调用站点做了很多我们不需要过多介绍的魔术,但是当一个对象实现IDynamicMetaObjectProvider动态调用站点(或者使用的活页夹)调用GetMetaObjecthttp://msdn.microsoft.com/en- us/library/system.dynamic.idynamicmetaobjectprovider.getmetaobject.aspx)在所述对象上。

ADynamicMetaObject的作用是描述如何对给定对象执行动态操作。在您的情况下,动态操作是“读取名为 Id 的属性”,因此调用站点调用BindGetMember动态元对象。这BindGetMember可以做任何它喜欢的事情,但是,在DynamicObject它调用自身TryGetMember的情况下。DynamicObject

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

例如,如果我这样做:

dynamic test = "test";
int length = test.Length;

test(这显然是一个字符串)没有方法TryGetMember。但是,CSharpGetMemberBinder知道如何使用反射来找出string具有名为的属性Length并返回它。

于 2013-07-26T08:08:57.247 回答
3

当您尝试访问 a 上的属性时DynamicObectDLR会在运行时调用其TryGetMember方法(请参阅WebGridRow 如何实现它)。你得到的是该方法的结果,通过它的out参数提供。

这里最重要的细节是您的 lambda 函数参数item没有键入为WebGridRow-- 在这种情况下,此代码将无法编译。动态性的实现是因为 的签名将参数WebGrid.Column声明为- 它是允许 DLR 接管的参数类型。formatFunc<dynamic, object>dynamic

于 2013-07-26T07:45:47.283 回答