mam następujące klasyGet wartość parametru z Expression Linq
public class MyClass
{
public bool Delete(Product product)
{
// some code.
}
}
Teraz mam klasy pomocnika, który wygląda tak
public class Helper<T, TResult>
{
public Type Type;
public string Method;
public Type[] ArgTypes;
public object[] ArgValues;
public Helper(Expression<Func<T, TResult>> expression)
{
var body = (System.Linq.Expressions.MethodCallExpression)expression.Body;
this.Type = typeof(T);
this.Method = body.Method.Name;
this.ArgTypes = body.Arguments.Select(x => x.Type).ToArray();
this.ArgValues = ???
}
}
Pomysł ist użyć tego kodu skądś:
// I am returning a helper somewhere
public Helper<T> GetMethod<T>()
{
var product = GetProduct(1);
return new Helper<MyClass>(x => x.Delete(product));
}
// some other class decides, when to execute the helper
// Invoker already exists and is responsible for executing the method
// that is the main reason I don't just comile and execute my Expression
public bool ExecuteMethod<T>(Helper<T> helper)
{
var instance = new MyClass();
var Invoker = new Invoker(helper.Type, helper.Method, helper.ArgTypes, helper.ArgValues);
return (bool)Invoker.Invoke(instance);
}
Punktem, w którym utknąłem, jest sposób wyodrębnienia argumentów z samego wyrażenia.
Znalazłem ten sposób
((ConstantExpression)((MemberExpression)body.Arguments[0]).Expression).Value
który wydaje się być typu obiektu z polem „produktu”, ale uważam, że musi być prostsze rozwiązanie.
Wszelkie sugestie.
Aktualizacja
Wystarczy, aby wyjaśnić, że mój kod zmodyfikowany zgodnie z tym co chcę achive. W mojej prawdziwej aplikacji słowo mam już klasę, która robi to samo, ale bez drzewa wyrażenie:
var helper = new Helper(typeof(MyClass), "Delete",
new Type[] { typeof(Product) }, new object[] {product}));
Głównym powodem mojego Helper<T>
ma mieć kompilacji sprawdzanie, czy podpis jest poprawny sposób.
Aktualizacja 2
To jest moja obecna implementacja, czy istnieje lepszy sposób acces wartości, bez używania refleksji?
public Helper(Expression<Func<T, TResult>> expression)
{
var body = (System.Linq.Expressions.MethodCallExpression)expression.Body;
this.Type = typeof(T);
this.Method = body.Method.Name;
this.ArgTypes = body.Arguments.Select(x => x.Type).ToArray();
var values = new List<object>();
foreach(var arg in body.Arguments)
{
values.Add(
(((ConstantExpression)exp.Expression).Value).GetType()
.GetField(exp.Member.Name)
.GetValue(((ConstantExpression)exp.Expression).Value);
);
}
this.ArgValues = values.ToArray();
}
jest jakiś powód, dla którego nie można po prostu skompilować wyrażenie i wykonać to? A może to po prostu błądzić, aby nauczyć się drzew ekspresji? –
@ rbev +1 bicie mnie do tego. – Aron
Heck, dlaczego nie po prostu wywołać bezpośrednio 'Delete (produkt)'? – Aron