C # 4.0, методы на лету? - PullRequest
       28

C # 4.0, методы на лету?

5 голосов
/ 02 ноября 2009

С введением таких вещей, как печатание на клавиатуре, мне бы очень понравилось, если бы я на лету сочинял методы объекта, помимо методов расширения. Кто-нибудь знает, возможно ли это? Я знаю, что MS беспокоится о создании основы на лету, но они, кажется, опускают пальцы ног в воду.

Обновление: спасибо Павлу за разъяснения. Например, скажем, я возвращаю новый динамический объект из LINQ и хотел бы добавить некоторые методы к нему на лету.

Ответы [ 3 ]

11 голосов
/ 02 ноября 2009

В свете обновленного ответа вы на самом деле ищете не «динамические методы», а именно «динамические объекты», чтобы вы могли добавлять к ним новые свойства и методы во время выполнения. Если это правильно, то в .NET 4.0 вы можете использовать ExpandoObject в сочетании с dynamic:

dynamic foo = new ExpandoObject();
foo.Bar = 123; // creates a new property on the fly
int x = foo.Bar; // 123

// add a new method (well, a delegate property, but it's callable as method)
foo.Baz = (Func<int, int, int>)
    delegate(int x, int y)
    {
        return x + y;
    };

foo.Baz(1, 2); // 3

Вы также можете иметь «динамические методы» с деревьями выражений, и как только вы получите делегат для такого метода, вы также можете создать свойство, похожее на вызываемый метод, из него на ExpandoObject.

Для использования в запросах LINQ, к сожалению, нельзя использовать инициализаторы объектов с ExpandoObject; в простейшем случае следующее не скомпилируется:

var foo =  new ExpandoObject { Bar = 123; }

Причина в том, что Bar в этом случае будет рассматриваться статически как свойство ExpandoObject. Вам нужно, чтобы получатель был dynamic для включения этой функции, и нет способа сделать это внутри инициализатора объекта. В качестве обходного пути для использования в LINQ рассмотрим этот вспомогательный метод расширения:

public static dynamic With(this ExpandoObject o, Action<dynamic> init)
{
     init(o);
     return o;
}

Теперь вы можете использовать его таким образом:

from x in xs
select new ExpandoObject().With(o => {
    o.Foo = x;
    o.Bar = (Func<int, int>)delegate(int y) { return x + y; };
});
2 голосов
/ 02 ноября 2009
1 голос
/ 02 ноября 2009

Это было уже возможно с помощью DynamicMethod и / или MethodBuilder. Не уверен, считается ли это «беспокойством», как это было некоторое время назад, хотя в большинстве сценариев требуется динамическая сборка (хотя DynamicMethod можно использовать и без).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...