2011-08-17 17 views
8

Jak skonstruować drzewo wyrażeń dla string.IndexOf("substring", StringComparison.OrdinalIgnoreCase)?Drzewo wyrażeń dla metody String.IndexOf

Mogę go uruchomić bez drugiego argumentu: StringComparison.OrdinalIgnoreCase. Są to moje próby do tej pory:

var methodCall = typeof (string).GetMethod("IndexOf", new[] {typeof (string)}); 
Expression[] parms = new Expression[]{right, Expression.Constant("StringComparison.OrdinalIgnoreCase", typeof (Enum))}; 
var exp = Expression.Call(left, methodCall, parms); 
return exp; 

próbował Również w tym:

var methodCall = typeof (string).GetMethod(method, new[] {typeof (string)}); 
Expression[] parms = new Expression[]{right, Expression.Parameter(typeof(Enum) , "StringComparison.OrdinalIgnoreCase")}; 
var exp = Expression.Call(left, methodCall, parms); 
return exp; 

Proszę pamiętać, że mogę dostać pracy, jeśli pominąć parametr OrdinalIgnoreCase.

Dzięki

+2

Jak zawsze, gdy masz problemy, powinieneś powiedzieć, co jest nie tak z tym, co próbujesz - czy otrzymujesz wyjątek, błąd podczas kompilacji, po prostu złe zachowanie? Jeśli jest to błąd, jaki jest błąd? –

+0

Przepraszamy. Będę o tym pamiętać następnym razem, gdy zadaję pytania. Otrzymałem wyjątek ArgumentException. – ashokgelal

+0

Powinna pomóc: [jak-i-utworzyć-wyrażenie-drzewo-do-reprezentacji-string-zawieraćsterm-in] (http://stackoverflow.com/questions/278684/how-do-i-create- an-expression-tree-to-represent-string-containsterm-in-c) – nawfal

Odpowiedz

11

Podejrzewam, że są dwa problemy.

Pierwszym z nich jest sposób dostajesz metodę - jesteś prosząc dla metody z tylko jednego parametru ciąg, zamiast jednego z dwóch parametrów:

var methodCall = typeof (string).GetMethod("IndexOf", 
          new[] { typeof (string), typeof(StringComparison) }); 

Drugi jest wartość dajesz - powinna być rzeczywista wartość stałą, a nie ciąg znaków:

Expression[] parms = new Expression[] { right, 
    Expression.Constant(StringComparison.OrdinalIgnoreCase) }; 

EDIT: Oto pełna próbka robocza:

using System; 
using System.Linq.Expressions; 

class Test 
{ 
    static void Main() 
    { 
     var method = typeof (string).GetMethod("IndexOf", 
       new[] { typeof (string), typeof(StringComparison) }); 

     var left = Expression.Parameter(typeof(string), "left"); 
     var right = Expression.Parameter(typeof(string), "right"); 

     Expression[] parms = new Expression[] { right, 
       Expression.Constant(StringComparison.OrdinalIgnoreCase) }; 

     var call = Expression.Call(left, method, parms); 
     var lambda = Expression.Lambda<Func<string, string, int>> 
      (call, left, right); 

     var compiled = lambda.Compile(); 
     Console.WriteLine(compiled.Invoke("hello THERE", "lo t")); 
    } 
} 
+0

Czy istnieje sposób zrobić to samo dla metody 'zawiera'? – atp9

+0

@ atp9: Tak. Co próbowaliście i co poszło nie tak? –

+0

Próbowałem coś takiego: 'MethodInfo method = typeof (ciąg).GetMethod ("Zawiera", nowy [] {typof (ciąg), typeof (StringComparison)}); var expressionbody = System.Linq.Expressions.Expression.Call (prop, metoda, new [] {valuetocompare, System.Linq.Expressions.Expression.Constant (StringComparison.OrdinalIgnoreCase)}); 'Ale ten daje mi błąd – atp9

0

nie sprawdzić resztę, ale jeśli tylko enum stwarza problemy:

Expression.Constant(StringComparison.OrdinalIgnoreCase) 

lub

Expression.Constant(Enum.Parse(typeof(StringComparison), "OrdinalIgnoreCase"), typeof(Enum)); 

i masz więcej opcji. Lub sprawdź moją odpowiedź here.

Edytuj: zapomniałem o namaszczeniu.

3

Najprostszym sposobem na to byłoby je zdobyć poprzez lambda tak:

//the compiler will convert the lambda into an expression 
Expression<Func<string, string, int>> expression = (s1, s2) => s1.IndexOf(s2, StringComparison.OrdinalIgnoreCase); 
//compile the expression so we can call it 
var func = expression.Compile(); 
//outputs 2 
Console.WriteLine(func("Case Sensitive", "se sensitive")); 

Jest to o wiele bardziej czytelny i utrzymaniu niż ręcznie budowania drzewa wyrażenie.

Jestem nieustannie zaskoczony ilością ludzi, którzy nurkują bezpośrednio do ręcznego budowania drzew ekspresji. Nie ma potrzeby, aby kompilator mógł wykonać pracę za ciebie.

+2

+1, nie ma powodu, aby budować drzewo wyrażeń ręcznie, gdy kompilator może to zrobić dla ciebie. –

+1

@Thomas: Tak, ale nie możemy zobaczyć, skąd pochodzą 'left' i' right' ... ponownie przypuszczalnie typu "Wyrażenie", a nie "ciąg". –

+0

Być może jest to lepszy sposób, ale biblioteka, nad którą pracuję (https://github.com/ashokgelal/NetFilterFramework) została zbudowana na podstawie ręcznego budowania drzewa wyrażeń. Na razie muszę tylko dodać wywołanie metody porównywania ciągów znaków, ale może to być konieczne do refaktoryzacji/przepisania wszystkiego przy użyciu lambdas. – ashokgelal

Powiązane problemy