2013-08-19 20 views
5

Sto cercando di chiamare una funzione in una dichiarazione prescelta LINQ dinamica, ma im errore di ottenere:la funzione di chiamata in LINQ dinamica

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

codice Esempio:

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

Come devo cambiare il mio codice per farlo funzionare?

Se chiamo la funzione integrata Convert.ToInt32, ad esempio, funziona correttamente.

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

Inoltre come faccio ho lanciato una proprietà utilizzando LINQ dinamica?

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

Quale sintassi è quella in cui si utilizza una stringa nel metodo 'Enumerable.Select'? –

+0

@Bob. Scritto nei tag: dynamic-linq – xanatos

risposta

8

dirò che il dynamic-linq non è "abbastanza forte" di fare queste cose. Sembra per i metodi solo negli oggetti esposti e alcune classi speciali: Math, Convert, i vari tipi di base (int, float, string, ...), Guid, Timespan, DateTime

L'elenco di questi tipi è chiaramente visibile se si utilizza ilspy/reflector sul file. Sono in System.Linq.Dynamic.ExpressionParser.predefinedTypes.

Ora, chiaramente potrei sbagliarmi, ma questo funziona: .Select("Guid.NewGuid().ToString()").Cast<string>().ToArray()

mostrando che è abbastanza probabile che questa è la lista "corretta".

C'è un articolo qui su come modificare dinamica LINQ, se siete interessati http://www.krizzcode.com/2012/01/extending-dynamiclinq-language.html

Ora, un uomo intelligente avrebbe preso la fonte di LINQ dinamica e semplicemente ampliare tale matrice ... Ma qui non ci sono uomini intelligenti ...Ci sono solo programmatori che vogliono sangue! Sangue ma soprattutto interiora!

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

fare questo (con i tipi che si desidera) prima che la prima chiamata a Dinamico Linq (perché dopo la prima chiamata ai metodi/proprietà di questi tipi vengono memorizzati nella cache)

Spiegazione: usiamo riflessione da aggiungere i nostri oggetti a questa "lista speciale".

+0

Invece di rispondere se poteva essere un suggerimento .... – andy

+1

@andy Una risposta che non è possibile è ancora una risposta – xanatos

+0

Grazie per i puntatori @xanatos – Magnus

0
var b = new[]{ a }; 

La matrice di cui sopra è non so che tipo di matrice, e non è il tipo di sicurezza?

I vostri valori vengono assegnati in tipo di dati Variant quindi non è valore intero (credo valore stringa), quando si ottiene questi valori nella query necessario bisogno di convert.toint32() perché il vostro tipo di classe di parametro di dati è integer

si prega di provare

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

invece di var b = new[]{ a };

Il suggerimento importante è qui (in grassetto):

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

E prega di guardare questo per la discussione precedente:

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

0

I può essere confuso, ma la sintassi con cui si utilizza una stringa nella vostra Select s non compilare per me. La seguente sintassi funziona:

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

'i tuoi selezioni non vengono compilati per me' perché OP utilizza 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 quindi ero confuso :) –

0

le seguenti opere per me:

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

So che c'è già una risposta accettata su questo, ma non ha funzionato per me. Sto usando Dynamic Linq 1.1.4. Volevo fare una domanda come questa

$.GetNewestRisk() == null 

Dove GetNewestRisk() è un metodo pubblico sull'oggetto rappresentato da $. Ho riscontrato questo errore "Errore durante l'esecuzione della query, i metodi sul tipo" Paziente "non sono accessibili (nell'indice 2)".

Ho trovato nel codice sorgente c'è un oggetto GlobalConfig che consente di assegnare un fornitore personalizzato che conterrà tutti i tipi con cui potresti voler lavorare. Ecco il codice sorgente per il provider personalizzato:

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

ecco come lo sto usando:

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

Dopo aver effettuato questa chiamata sono in grado di chiamare i metodi sugli oggetti all'interno dell'espressione.

+0

Sono stato in grado di adattare questa risposta a System.Linq.Dynamic.Core. Ha la stessa interfaccia ma ha anche ParsingConfig che ti permette di fornire tipi a singole espressioni piuttosto che applicare i tipi personalizzati a livello globale. – Kent

Problemi correlati