Domanda

Sto lavorando a un metodo che accetta un albero delle espressioni come parametro, insieme a un tipo (o istanza) di una classe.

L'idea di base è che questo metodo aggiungerà alcune cose a una raccolta che verrà utilizzata per la convalida.

public interface ITestInterface
{
    //Specify stuff here.
}

private static void DoSomething<T>(Expression<Func<T, object>> expression, params IMyInterface[] rule)
{
    // Stuff is done here.
}

Il metodo si chiama come segue:

class TestClass
{
    public int MyProperty { get; set; }
}

class OtherTestClass  : ITestInterface
{
    // Blah Blah Blah.
}

static void Main(string[] args)
{
    DoSomething<TestClass>(t => t.MyProperty, 
        new OtherTestClass());
}

Lo sto facendo in questo modo perché mi piacerebbe che i nomi delle proprietà che venivano passati fossero tipizzati in modo forte.

Un paio di cose con cui sto lottando ..

  1. In DoSomething, vorrei ottenere un tipo PropertyInfo (dal corpo passato) di T e aggiungerlo a una raccolta insieme alla regola []. Attualmente, sto pensando di usare expression.Body e di rimuovere [nome proprietà] da " Convert. ([Nome proprietà]) " e usando la riflessione per ottenere ciò di cui ho bisogno. Sembra ingombrante e sbagliato. C'è un modo migliore?
  2. È uno schema specifico che sto usando?
  3. Infine, sono apprezzati eventuali suggerimenti o chiarimenti sul mio fraintendimento di ciò che sto facendo e / o risorse o buone informazioni sugli alberi delle espressioni C #.

Grazie!

Ian

Modifica:

Un esempio di ciò che expression.Body.ToString () restituisce all'interno del metodo DoSomething è una stringa che contiene " Convert (t.MyProperty) " se chiamato dall'esempio sopra.

Ho bisogno che sia fortemente tipizzato, quindi non verrà compilato se cambio un nome di proprietà.

Grazie per i suggerimenti!

È stato utile?

Soluzione

Raccolta di oggetti PropertyInfo da Expression.Body sembra simile a la mia soluzione ad un'altra domanda.

Altri suggerimenti

Mi affido fortemente agli alberi delle espressioni per spingere molto di ciò che voglio fare con la mia attuale applicazione per la compilazione in tempo, ovvero il controllo statico del tipo.

Attraverso gli alberi delle espressioni per tradurli in qualcos'altro che "ha senso".

Una cosa che ho finito per fare molto è che al posto degli URL mi affido ad un approccio simile a MVC in cui dichiaro funzioni lambda e traduco che ... interpretano, il compilatore ha generato l'albero delle espressioni in un URL. Quando viene invocato questo URL, faccio il contrario. In questo modo, ho quello che chiamo controlli in fase di compilazione per collegamenti interrotti e questo funziona benissimo anche con refactoring e sovraccarichi. Penso che sia bello pensare di usare gli alberi delle espressioni in questo modo.

Potresti voler controllare il modello di visitatore, è un dolore iniziare perché non ha molto senso all'inizio ma lega tutto insieme ed è un modo molto formale per risolvere il controllo del tipo nella costruzione del compilatore. Potresti fare lo stesso, ma invece di controllare il tipo emetti tutto ciò di cui hai bisogno.

Qualcosa su cui sto battendo la testa è la capacità di costruire un semplice framework per tradurre (o in realtà dovrei dire interpretare) espressione tress ed emettere JavaScript. L'idea è che gli alberi delle espressioni generati dal compilatore si tradurranno in JavaScript valido che si interfaccia con alcuni modelli di oggetti.

La cosa interessante di questo è il modo in cui il compilatore è sempre in grado di dirmi quando sbaglio e sicuro che il risultato finale sia solo un mucchio di stringhe, ma la parte importante è come queste stringhe sono state create. Hanno superato alcune verifiche e questo significa qualcosa.

Una volta che lo fai, c'è poco che non puoi fare con gli alberi delle espressioni.

Mentre lavoravo con System.Reflection.Emit roba, mi sono ritrovato a usare alberi delle espressioni per creare un framework leggero per la compilazione dinamica, che al momento della compilazione poteva sostanzialmente dire se anche i miei assembly creati dinamicamente si sarebbero compilati, e ha funzionato perfettamente con la riflessione e il controllo del tipo statico. Ci è voluto ancora di più e alla fine è arrivato a qualcosa che alla fine ha risparmiato molto tempo e si è rivelato molto agile e robusto.

Quindi adoro questo genere di cose, e questo è ciò che riguarda la meta-programmazione, scrivere programmi nei tuoi programmi che fanno programmi. Dico che continui a venire!

Apprezzo quello che stai cercando di fare con la proprietà qui. Mi sono imbattuto in questo enigma. È sempre strano scrivere:

DoSomething("MyProperty", new OtherClass());

Se la proprietà cambia nome o il testo viene digitato in modo errato nella chiamata, si verificherà un problema. Quello che ho imparato è che questo è qualcosa che probabilmente dovrai affrontare tramite i test. In particolare, test unitari. Scriverei test unitari per imporre che il "DoSomething" le chiamate funzionano correttamente.

L'altra cosa che potresti provare è decorare le tue proprietà con attributi e quindi riflettere contro la tua classe quando è costruita cercando proprietà con l'attributo e caricare le regole.

[DoSomething(typeof(OtherClass), typeof(OtherClass2))]
public int MyProperty
{
  get;
  set;
}

In questo caso il costruttore (forse in una classe base?) creerebbe dinamicamente un oggetto OtherClass e un oggetto OtherClass2 e li caricherà in una raccolta insieme al nome della proprietà.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top