2014-04-19 9 views
5

Potrzebuję utworzyć System.Linq.Expressions.Expression, który wywołuje dynamiczny obiekt. Obiektem dynamicznym może być ExpandoObject lub dowolny inny.Prawidłowy sposób konstruowania wyrażenia .NET do wywoływania obiektów dynamicznych

Rozważmy następujący test:

var myInstance = DateTime.Now; 

var methodInfo = myInstance.GetType().GetMethod("ToUniversalTime"); 

var methodCallExpression = Expression.Call(Expression.Constant(myInstance), methodInfo); 
var expression = Expression.Lambda(methodCallExpression); 

Assert.AreEqual(myInstance.ToUniversalTime(), expression.Compile().DynamicInvoke()); 

muszę stworzyć odpowiednik wyraz podczas myInstance deklaruje podobne (tylko jako przykład):

dynamic myInstance = new ExpandoObject(); 
myInstance.MyMethod = new Func<string>(() => "hello world"); 

Przypuszczam, że muszę korzystać Expression.Dynamic metoda (patrz MSDN). Ale nie wiem, jak z niego korzystać. Próbowałem szukać na google, ale tylko przykłady, które znalazłem użyć klasy Microsoft.CSharp.RuntimeBinder.Binder (patrz MSDN), które nie mogą być oficjalnie używany:

Ten interfejs API obsługuje infrastrukturę programu .NET Framework i nie jest przeznaczony do stosowania bezpośrednio z Twojego kodu.

Korzystanie Microsoft.CSharp.RuntimeBinder.Binder mogę napisać poniższy kod:

dynamic myInstance = new ExpandoObject(); 
myInstance.MyMethod = new Func<string>(() => "hello world"); 

var binder = Binder.InvokeMember(
    CSharpBinderFlags.None, 
    "MyMethod", 
    null, 
    this.GetType(), 
    new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant, null) }); 

var methodCallExpression = Expression.Dynamic(binder, typeof(object), Expression.Constant(myInstance)); 
var expression = Expression.Lambda(methodCallExpression); 

Assert.AreEqual(myInstance.MyMethod(), expression.Compile().DynamicInvoke()); 

Jest to rozwiązanie prawidłowe?

+1

Tak, tak to zaimplementowałem w CSharpEval – EnderWiggin

Odpowiedz

-1
dynamic x = typeof("<<MethodName>>") 
      .GetMethod("ToUniversalTime") 
      .Invoke(<<Type Of Object>>, new object[] { [Parameter1,]      
      [Parameter2,....] }); 

w tym kodzie „Typ” zamiast z którego typ obiektu trzeba wywołać metodę ...

określić nazwę metody zamiast „MethodName”

iw końcu zamiast Twojego obiektu „Rodzaj obiektu”

a jeśli nie ma parametr następnie przekazać pustą tablicę ... inne mądry przejść zamiast „parameter1,2, i tak dalej.

+1

Szukam sposobu na skonstruowanie drzewa wyrażeń, patrz Klasa Expression. Twój kod wywołuje metid poprzez odbicie. –

1

Oto kot ch: z mojego rozumowania nie ma sensu w nawiązywaniu połączenia dynamicznego bez jakiegoś obiektu Binder.

Przedmiotem spoiwo przedstawia zasady, które są następnie do dynamicznego rozpoznawania nazw:

  • Jeżeli mecz jest wielkość liter?
  • Jak należy rozładować metody?
  • Co zrobić, jeśli obiekt jest obiektem niedynamicznym?
  • Jakie awarie używasz?

Innymi słowy, przedmiotem Binder reprezentuje semantykę powołania „język”, natomiast IDynamicMetaObjectProvider reprezentuje semantykę nazwie obiektu.

Tak, tak, nie powinniśmy używać obiektu CSharp Binder. To może być odczuwalne szczególnie wtedy, gdy pojawiają się pewne problemy, które można obejść tylko za pomocą wewnętrznych elementów obiektu. Jednak alternatywą jest po prostu użycie innej, nieinterfejsowej, implementacji Binder.

Powiązane problemy