2009-11-02 13 views
5

Wraz z wprowadzeniem takich rzeczy jak pisanie na maszynie do pisania kaczuszką, bardzo bym chciał, gdybym komponował metody obiektów w locie, poza metodami rozszerzenia. Czy ktoś wie, czy to możliwe? Wiem, że stwardnienie rozsiane obawia się komponowania ramy w locie, ale oni wydają się zanurzać ich palce u nóg w wodzie.C# 4.0, Metody w locie?

Aktualizacja: Podziękowania dla Pavela za wyjaśnienie. Na przykład, powiedz, że zwracam nowy obiekt dynamiczny z LINQ i chciałbym dodać do niego kilka metod w locie.

+0

masz na myśli runtieme generowanie kodu? Czy chodzi ci o dynamiczne dodawanie metod do obiektów, a la JavaScript? –

+0

The later. Wygląda na to, że możesz to zrobić z drzewkami ekspresji, ale co to jest PITA. – Trent

Odpowiedz

11

W świetle zaktualizowanego odpowiedź, nie jesteś rzeczywiście patrząc na „metod dynamicznych”, tak bardzo jak „dynamicznych obiektów” - takie, które można dodawać nowe właściwości i metody do nich w czasie wykonywania. Jeśli to prawda, to w .NET 4.0, można użyć ExpandoObject w połączeniu z 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 

Można mieć „metod dynamicznych”, która za pomocą wyrażenia drzew, a po uzyskaniu delegata dla takiego sposobu można również utworzyć z niego metodę wywoływania podobną do metody na ExpandoObject.

Do użytku w kwerendach LINQ niestety nie można używać inicjalizatorów obiektów z ExpandoObject; w najprostszym przypadku, dodaje się nie skompiluje:

var foo = new ExpandoObject { Bar = 123; } 

Powodem jest to, że Bar w tym przypadku będzie spojrzał statycznie jako własność ExpandoObject. Aby ta funkcja mogła zostać wciągnięta, potrzebny jest odbiornik dynamic i nie ma możliwości, aby została wykonana wewnątrz inicjalizatora obiektu. Jako obejście do użytku w LINQ, należy rozważyć tę metodę pomocnika rozszerzeń:

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

Teraz można go używać w następujący sposób:

from x in xs 
select new ExpandoObject().With(o => { 
    o.Foo = x; 
    o.Bar = (Func<int, int>)delegate(int y) { return x + y; }; 
}); 
+0

Nice! Co się stanie, jeśli utworzę obiekt dynamiczny z LINQ (zwracając określone właściwości), czy to obiekt ExpandoObject, do którego mogę dodać metody? – Trent

+0

Typy anonimowe (utworzone za pomocą 'nowego {...}' bez klasy określonej po 'nowym ') nie są rozwijane. W pozostałej części artykułu sprawdź edytowaną odpowiedź. –

+0

To dobra robota. Wystarczy kilka poprawek składni, aby to skompilować. Zamień Action <> with Func <> i musisz wstawić ';' po dynamicznych kreacjach właściwości/metod zamiast "," – Trent

1

Było to już możliwe dzięki pomocy DynamicMethod i/lub MethodBuilder. Nie jestem pewien, czy to się liczy jako "zmartwionego", jak to miało miejsce od jakiegoś czasu, chociaż wymaga większości dynamicznych zespołów (DynamicMethod bez tego).

+0

Kiedy mówię o problemach, mam na myśli http://blogs.msdn.com/csharpfaq/archive/2004/03/09/86979.aspx. Miałem nadzieję na uniknięcie refleksji, ale dzięki za napiwek – Trent

+0

przykro, gra słów była nieco przeznaczona. Jak się przekonałeś, nie ma potrzeby używania refleksji. Dobra odpowiedź Pavel zapisał! – Abel