2013-08-19 15 views
5

Próbuję wywołać funkcję w dynamicznym linq select, ale im się błąd:funkcja połączeń w dynamicznym LINQ

No property or field 'A' exists in type 'Tuple2' 

Przykładowy kod:

void Main() 
{ 
    var a = new Tuple<int, int>(1,1); 
    var b = new[]{ a }; 
    var q = b.AsQueryable().Select("A.Test(it.Item1)"); 

    q.Dump(); 
} 

public static class A 
{ 
    public static int Test(int i) 
    { 
     return i++; 
    } 
} 

Jak mogę zmienić kod, aby to działało?

Jeśli na przykład zadzwonię do wbudowanej funkcji Convert.ToInt32, to działa poprawnie.

var q = b.AsQueryable().Select("Convert.ToInt32(it.Item1)"); 

Również w jaki sposób rzutować właściwość za pomocą dynamicznego linq?

var q = b.AsQueryable().Select("((float)it.Item1)"); 
+0

Jaka jest składnia w przypadku użycia ciągu znaków w metodzie "Enumerable.Select"? –

+0

@Bob. Napisane w tagach: dynamic-linq – xanatos

Odpowiedz

8

powiem że dynamic-linq nie jest „wystarczająco silny”, aby robić te rzeczy. Wygląda na metodach tylko w podanych przedmiotów i niektórych szczególnych klas: Math, Convert, różnych typów bazowych (int, float, string, ...) Guid, Timespan, DateTime

Lista tych typów jest wyraźnie widoczny, jeśli używasz ilspy/reflector na pliku. Są one w System.Linq.Dynamic.ExpressionParser.predefinedTypes.

Teraz jasno mogę się mylić, ale to działa: .Select("Guid.NewGuid().ToString()").Cast<string>().ToArray()

pokazując, że to całkiem prawdopodobne, że to jest „poprawny” lista.

Jest tu artykuł o tym, jak zmodyfikować Dynamiczne LINQ jeśli jesteś zainteresowany http://www.krizzcode.com/2012/01/extending-dynamiclinq-language.html

Teraz inteligentny człowiek weźmie źródło dynamicznej LINQ i po prostu rozwinąć tę tablicę ... Ale tu nie ma inteligentni mężczyźni ...Są tylko programiści, którzy chcą krwi! Krew, ale w szczególności innards!

var type = typeof(DynamicQueryable).Assembly.GetType("System.Linq.Dynamic.ExpressionParser"); 

FieldInfo field = type.GetField("predefinedTypes", BindingFlags.Static | BindingFlags.NonPublic); 

Type[] predefinedTypes = (Type[])field.GetValue(null); 

Array.Resize(ref predefinedTypes, predefinedTypes.Length + 1); 
predefinedTypes[predefinedTypes.Length - 1] = typeof(A); // Your type 

field.SetValue(null, predefinedTypes); 

zrobić (z typami chcesz) przed pierwszym wywołaniem dynamicznym Linq (ponieważ po pierwsze wywołanie metody/właściwości tych typów są buforowane)

Objaśnienie: używamy odbicie dodać nasz obiekt (y) do tej "specjalnej listy".

+0

Zamiast odpowiedzi, czy może to być sugestia ... – andy

+1

@andy Odpowiedź, że nie jest to możliwe wciąż odpowiedź – xanatos

+0

Dzięki za wskazówki @xanatos – Magnus

0
var b = new[]{ a }; 

Powyższa tablica jest nie wiem jaki rodzaj tablicy, a to nie jest typ jest bezpieczne?

Twoje wartości są przypisane w typie danych wariantu więc nie jest wartością całkowitą (myślę, że wartość ciągu), gdy pojawi się tych wartości w zapytaniu musi trzeba convert.toint32(), ponieważ typ danych parametru klasa jest liczbą całkowitą

Proszę spróbować

var b = new **int**[]{ a }; 

zamiast var b = new[]{ a };

ważna wskazówka jest tutaj (pogrubione):

No property or field 'xxx' exists in **type** 'xxx' 

I proszę spojrzeć na ten poprzedniej dyskusji:

Dynamic Linq - no property or field exists in type 'datarow'

0

mogę się mylić, ale składnia której używasz ciąg w swoim Select s nie skompilować dla mnie. Poniższa składnia działa:

var q = b.AsQueryable().Select(it => A.Test(it.Item1)); 
+1

'Twój Selects nie kompiluje się dla mnie' ponieważ OP używa dynamic-linq http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part -1-using-the-linq-dynamic-query-library.aspx – I4V

+0

Ah, więc byłem zdezorientowany :) –

0

następujące prace dla mnie:

var a = new Tuple<int, int>(1, 1); 
var b = new[] { a }; 
var q = b.AsQueryable().Select(it=>A.Test(it.Item1)); 
var q1 = b.AsQueryable().Select(it => Convert.ToInt32(it.Item1)); 
var q2 = b.AsQueryable().Select(it => (float) it.Item1); 
6

wiem, że jest już akceptowane odpowiedź na to, ale to nie działa dla mnie. Używam Dynamic Linq 1.1.4. Chciałem wykonać zapytanie takie jak to, gdzie GetNewestRisk() jest publiczną metodą na obiekcie reprezentowanym przez $. Ciągle otrzymuję ten błąd "Błąd podczas uruchamiania zapytania, Metody typu" Pacjent "są niedostępne (w indeksie 2)".

Znalazłem w kodzie źródłowym obiekt GlobalConfig, który pozwala przypisać niestandardowego dostawcę, który będzie utrzymywał wszystkie typy, z którymi chciałbyś pracować. Oto kod źródłowy dla dostawcy niestandardowego:

public class CustomTypeProvider: IDynamicLinkCustomTypeProvider 
{ 
    public HashSet<Type> GetCustomTypes() 
    { 
     HashSet<Type> types = new HashSet<Type>(); 
     types.Add(typeof(Patient)); 
     types.Add(typeof(RiskFactorResult)); 
     types.Add(typeof(PatientLabResult)); 
     types.Add(typeof(PatientVital)); 
     return types; 
    } 
} 

Oto jak używam go:

System.Linq.Dynamic.GlobalConfig.CustomTypeProvider = new CustomType(); 

Po dokonaniu tego połączenia Jestem w stanie wywołać metody na obiektach wewnątrz wyrażenia.

+0

Byłem w stanie dostosować tę odpowiedź do System.Linq.Dynamic.Core. Ma ten sam interfejs, ale ma również ParsingConfig, który pozwala na dostarczanie typów do poszczególnych wyrażeń, zamiast stosować typy niestandardowe na całym świecie. – Kent

Powiązane problemy