2013-07-26 4 views
1

Я просто не могу представить следующий код вместе в исходном коде MVC Webgrid.DynamicObject? Как работает следующий код?

Когда мы строим столбец сетки, мы сказать

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

«элемент» является параметром лямбда, очевидно, и это на самом деле «WebGridRow» класса. (Я ДУМАЮ !! если я не ошибаюсь) Посмотреть исходный код здесь

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

Мой вопрос здесь, «Id» не является свойством этого класса и так WebGridRow наследует от DynamicObject, как именно " .Id "сопоставлено с" исходным объектом "текущей строки?

Btv, исходный объект "значение объекта" передается через конструктор 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); 
     .... 
} 

ответ

6

[Редактировать]
Я написал довольно обширный блог-пост на эту тему здесь: http://blog.alxandr.me/2013/07/26/dynamic-dispatch-how-dynamic-work-in-c/ Если вы заинтересованы в том, как динамической диспетчеризации в работах C#, это может объяснить, совсем немного.
[/ Edit]

Я много работал с DLR, и это огромный и сложный зверь, но я буду стараться держать это просто.

Что происходит, когда вы делаете что-либо с dynamic в C#, это то, что компилятор создает динамический сайт-вызов. Если вы декомпилируете код, в большинстве случаев вы получите что-то вроде CallSite<Func<CallSite, object, object, object>> (а не функции, они имеют более двух параметров). Сайт-вызов делает много магии, что нам не нужно слишком много вникать, но когда объект реализует IDynamicMetaObjectProvider, динамический call-сайт (или скорее используемое связующее) вызывает GetMetaObject (http://msdn.microsoft.com/en-us/library/system.dynamic.idynamicmetaobjectprovider.getmetaobject.aspx) на указанном объекте.

A DynamicMetaObject Роль состоит в том, чтобы описать, как выполнять динамические операции с данным объектом.В вашем случае динамическая операция - это свойство чтения с именем Id, поэтому вызывающий абонент вызывает BindGetMember на динамическом метаобъекте. Этот BindGetMember может делать все, что ему нравится, однако в случае DynamicObject он вызывает TryGetMember на самом DynamicObject.

Теперь, есть много кэширования (и черная магия), участвующие, что делает это эффективно, и DynamicObject обеспечивает простой способ для реализации IDynamicMetaObjectProvider (который может быть настоящим зверь, чтобы получить право на раз), но это все еще Безразлично 't означает, что каждый объект dynamic является DynamicObject.

Например, если я делаю это:

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

test (который, очевидно, строка) не имеет какого-либо метода TryGetMember. Однако CSharpGetMemberBinder знает, как использовать отражение, чтобы выяснить, что string имеет свойство Length и возвращает это.

+0

Святая моля @ Алксандр! Спасибо, что помогли мне два раза подряд! Я слишком устал прошлой ночью, пытаясь собрать вместе загадку. Какой отличный пост в блоге! Мне, возможно, придется несколько раз прочитать, чтобы полностью «получить». но спасибо и @ Jon за то, что объяснили мне эту пьесу. Если смогу, я бы проголосовал за ваши ответы как лучший ответ для меня в этом году! – Liming

3

При попытке доступа к свойству на DynamicObect, то DLR вызывает метод TryGetMember во время выполнения (см how WebGridRow implements it). То, что вы получаете, это результат этого метода, предоставляемый через его параметр out.

Важнейшая деталь здесь заключается в том, что ваш аргумент лямбда-функции item не напечатан как WebGridRow - в этом случае этот код не будет компилироваться. Динамизм достигается потому, что подпись WebGrid.Column объявляет параметр format как Func<dynamic, object> - это тип аргумента dynamic, который позволяет использовать DLR.

+0

Ah ha !! Спасибо вам большое @ Jon !! Я совсем не знаком с DynamicObject, снова узнал что-то сегодня! Большое большое спасибо! – Liming

+0

@Liming: 'DynamicObject' сам по себе не способен это сделать - важная часть состоит в том, что' item' вводится как 'dynamic'. Я добавил некоторые разъяснения. – Jon

+0

Я хотел бы отметить, что это несколько неправильно. В случае с «DynamicObject» это верно, но это связано с тем, как «DynamicObject» реализует «IDynamicMetaObjectProvider». – Alxandr

Смежные вопросы