2011-10-22 6 views
6

Próbuję utworzyć drzewo wyrażeń. Potrzebuję odczytać dane z tabeli danych i sprawdzić ich kolumny. Kolumny do sprawdzenia oraz liczba kolumn do sprawdzenia są znane tylko w czasie wykonywania. Nazwy kolumn są mi podane jako tablica znaków, a każda kolumna ma listę ciągów do sprawdzenia. Próbowałem drzewek wyrażeń przykładowych, jak ten poniżej.BŁĄD Metoda statyczna wymaga wystąpienia zerowego, metoda niestatyczna wymaga niezerowej instancji

Tutaj napotykam błąd.

Metoda statyczna wymaga instancji zerowej, metoda niestatyczna wymaga wystąpienia o wartości niezerowej. nazwa parametrów: przykład

na linii

wewnętrzna = Expression.Call (rowexp m; colexp);

Uprzejmie mi pomóc!

IQueryable<DataRow> queryableData = CapacityTable 
    .AsEnumerable() 
    .AsQueryable() 
    .Where(row2 => values.Contains(row2.Field<string>("Head1").ToString()) 
       && values.Contains(row2.Field<string>("Head2").ToString())); 

MethodInfo mi = typeof(DataRowExtensions).GetMethod(
    "Field", 
     new Type[] { typeof(DataRow),typeof(string) }); 

mi = mi.MakeGenericMethod(typeof(string)); 

ParameterExpression rowexp = Expression.Parameter(typeof(DataRow), "row"); 
ParameterExpression valuesexp = Expression.Parameter(typeof(List<string>), "values"); 
ParameterExpression fexp = Expression.Parameter(typeof(List<string>), "types"); 
Expression inner, outer, predicateBody = null; 

foreach (var col in types) 
{ 
    // DataRow row = CapacityTable.Rows[1]; 

    ParameterExpression colexp = Expression.Parameter(typeof(string), "col"); 
    // Expression left = Expression.Call(pe, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes)); 

    inner = Expression.Call(rowexp,mi, colexp); 
    outer = Expression.Call(valuesexp, typeof(List<string>).GetMethod("Contains"), inner); 
    predicateBody = Expression.And(predicateBody,outer); 
} 

MethodCallExpression whereCallExpression = Expression.Call(
    typeof(Queryable), 
    "Where", 
    new Type[] { queryableData.ElementType }, 
    queryableData.Expression, 
    Expression.Lambda<Func<DataRow,bool>>(predicateBody, new ParameterExpression[] { rowexp })); 

Odpowiedz

9

Oznacza to, że wywołanie metody, które próbujesz reprezentować, jest statyczne, ale podajesz mu wyrażenie docelowe. To tak, jakby próbować wywołać:

Thread t = new Thread(...); 
// Invalid! 
t.Sleep(1000); 

Próbujesz to zrobić w formie drzewa ekspresyjnego, co również jest niedozwolone.

Wygląda na to, że to się dzieje w przypadku metody Field przedłużenia na DataRowExtensions - tak „target” metody wydłużania musi być wyrażona jako pierwszy argumentu na wezwanie, bo rzeczywiście chcesz zadzwonić:

DataRowExtensions.Field<T>(row, col); 

Więc chcesz:

inner = Expression.Call(mi, rowexp, colexp); 

że wezwie this overload który jest drogą do wywołania metody statyczne z dwoma argumentami.

+0

Czy możesz omówić nieco wyżej? Dlaczego podajesz tutaj Method info jako pierwszy argument metody Expression.Call? – Kobojunkie

+0

@Kobojunkie: Ponieważ w ten sposób mówisz 'Expression.Call' jaka metoda statyczna nas interesuje. Zobacz http://msdn.microsoft.com/en-us/library/bb301084.aspx –