2013-08-19 14 views
5

Ich versuche, eine Funktion in einer dynamischen Linq select-Anweisung zu nennen, aber im Fehler bekommen:Anruffunktion in dynamischer Linq

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

Beispielcode:

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++; 
    } 
} 

Wie soll ich meine ändern Code, damit das funktioniert?

Wenn ich zum Beispiel integrierte Funktion aufrufen, funktioniert es gut.

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

Auch wie kann ich eine Eigenschaft werfen dynamische Linq verwenden?

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

Welche Syntax verwenden Sie, wenn Sie eine Zeichenfolge in der 'Enumerable.Select' Methode verwenden? –

+0

@Bob. In den Tags geschrieben: dynamic-linq – xanatos

Antwort

8

Ich werde sagen, dass die dynamic-linq nicht „stark genug“, um diese Dinge zu tun. Es sucht nach Methoden nur in den angegebenen Objekten und einigen speziellen Klassen: Math, Convert, die verschiedenen Basistypen (int, float, string, ...), Guid, Timespan, DateTime

Die Liste dieser Arten ist deutlich sichtbar, wenn Sie ilspy/reflector für die Datei verwenden. Sie sind in System.Linq.Dynamic.ExpressionParser.predefinedTypes.

Nun, klar könnte ich falsch sein, aber dies funktioniert: .Select("Guid.NewGuid().ToString()").Cast<string>().ToArray()

zeigt, dass es sehr wahrscheinlich ist, dass die „richtige“ -Liste ist.

Es gibt einen Artikel hier, wie dynamische LINQ zu ändern, wenn Sie http://www.krizzcode.com/2012/01/extending-dynamiclinq-language.html

Jetzt interessiert sind, ein intelligenter Mann die Quelle dynamischer Linq nehmen würde und einfach das Array erweitern ... Aber hier gibt es nicht intelligente Männer ...Es gibt nur Programmierer, die Blut wollen! Blut aber vor allem Innereien!

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); 

dies tun (mit den Typen, die Sie wünschen) vor dem ersten Aufruf zu Dynamische Linq (denn nach der ersten die Methoden/Eigenschaften dieser Typen nennen werden zwischengespeichert)

Erläuterung: wir Reflexion verwenden hinzufügen unser Objekt (e) zu dieser "speziellen Liste".

+0

Statt zu antworten, wenn es ein Vorschlag sein könnte .... – andy

+1

@andy Eine Antwort, die es nicht möglich ist immer noch eine Antwort – xanatos

+0

Danke für die Zeiger @xanatos – Magnus

0
var b = new[]{ a }; 

Die obige Anordnung ist nicht wissen, welche Art von Array, und es ist nicht sicher geben?

sind Ihre Werte in Variant-Datentyp zugeordnet, damit es nicht ganzzahligen Wert ist (ich glaube, String-Wert), wenn Sie erhalten diese Werte in Ihrer Anfrage benötigen müssen(), um Convert.ToInt32 weil Ihre Klassentyp Parameterdaten integer ist

Bitte versuchen sie es

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

statt var b = new[]{ a };

der wichtige Hinweis hier ist (fett gedruckt):

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

Und das für Sie aussehen vorherige Diskussion:

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

0

ich verwechselt werden können, aber Ihre Syntax wodurch Sie eine Zeichenfolge in Ihrem Select s unter Verwendung von nicht kompiliert für mich. Die folgende Syntax funktioniert:

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

'Ihre Selects kompiliert für mich nicht, weil OP dynamische-linq http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part verwendet -1-using-the-linq-dynamic-query-library.aspx – I4V

+0

Ah so war ich verwirrt :) –

0

Die folgenden Werke für mich:

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

Ich weiß, dass es bereits eine akzeptierte Antwort auf diese, aber es nicht für mich arbeiten. Ich benutze Dynamic Linq 1.1.4. Ich wollte eine Abfrage wie diese

$.GetNewestRisk() == null 

tun Wo GetNewestRisk() eine öffentliche Methode für das Objekt ist von $ dargestellt. Ich habe diesen Fehler erhalten "Fehler beim Ausführen der Abfrage, Methoden vom Typ 'Patient' sind nicht verfügbar (in Index 2)".

Ich fand im Quellcode ein GlobalConfig-Objekt, das es ermöglicht, einen benutzerdefinierten Anbieter zuzuweisen, der alle Typen enthält, mit denen Sie arbeiten möchten. Hier ist der Quellcode für den benutzerdefinierten Anbieter:

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; 
    } 
} 

Hier ist, wie ich es bin mit:

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

Nach diesem Aufruf ich in der Lage bin Methoden aufrufen auf die Objekte innerhalb des Ausdrucks.

+0

Ich konnte diese Antwort an System.Linq.Dynamic.Core anpassen. Es hat dieselbe Schnittstelle, aber es verfügt auch über ParsingConfig, mit dem Sie Typen für einzelne Ausdrücke bereitstellen können, anstatt die benutzerdefinierten Typen global anzuwenden. – Kent