我似乎无法在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”中的“格式”功能
private static HelperResult Format(Func<dynamic, object> format, dynamic arg) {
var result = format(arg);
....
}
答案 0 :(得分:6)
<强> [编辑] 强>
我在这里写了一篇关于这个主题的相当广泛的博客文章:http://blog.alxandr.me/2013/07/26/dynamic-dispatch-how-dynamic-work-in-c/
如果您对C#中的动态调度如何工作感兴趣,这可能会解释相当多
的 [/编辑] 强>
我在DLR上做了很多工作,这是一个庞大而复杂的野兽,但我会尽量保持这个简单。
当您在C#中使用dynamic
执行任何操作时,会发生什么,编译器会生成动态调用站点。如果您对代码进行反编译,那么在大多数情况下,您最终会得到类似CallSite<Func<CallSite, object, object, object>>
的内容(而不是函数,它们往往会有超过2个参数)。调用站点做了很多我们不需要过多的魔术,但是当一个对象实现IDynamicMetaObjectProvider
时,动态调用点(或者使用的绑定器)会调用GetMetaObject
({{ 3}})对所说的对象。
DynamicMetaObject
的作用是描述如何对给定对象执行动态操作。在您的情况下,动态操作是“读取属性名为Id”,因此调用点在动态元对象上调用BindGetMember
。这个BindGetMember
可以执行任何喜欢的操作,但是,DynamicObject
会在TryGetMember
上调用DynamicObject
。
现在,涉及到很多缓存(和黑魔法),这使得效率更高,DynamicObject
提供了一种实现IDynamicMetaObjectProvider
的简单方法(可以成为真正的野兽)时间),但这并不意味着每个dynamic
对象都是DynamicObject
。
例如,如果我这样做:
dynamic test = "test";
int length = test.Length;
test
(显然是一个字符串)没有方法TryGetMember
。但是CSharpGetMemberBinder
知道如何使用反射来确定string
有一个名为Length
的属性并返回该属性。
答案 1 :(得分:3)
当您尝试访问DynamicObect
上的媒体资源时,DLR会在运行时调用其TryGetMember
方法(请参阅how WebGridRow implements it)。您得到的是该方法的结果,通过其out
参数提供。
这里最重要的细节是你的lambda函数参数item
没有输入WebGridRow
- 在这种情况下,这段代码不能编译。动态是因为WebGrid.Column
的签名将format
参数声明为Func<dynamic, object>
- 它是允许DLR接管的参数的dynamic
类型。