2012-02-14 13 views
6

Sto lavorando a un progetto Web Forms che carica i risultati delle query Sql in DataTable s.Associazione dinamica all'oggetto aziendale personalizzato in Runtime

Questi DataTable s vengono passati al front-end in cui vengono associati a un controllo Web Repeater.

Questo funziona benissimo. Tuttavia, ora vorremmo associarci alle nostre classi personalizzate anziché a DataTable. Purtroppo, quello che pensavo fosse la risposta ovvia non ha funzionato (implementando IDictionary<string, object> sulla nostra classe).

Che cosa è necessario associare Eval a Datum senza creare una proprietà concreta per ogni associazione? Chiaramente DataRow non deve implementare concretamente tutte le proprietà che leghiamo. Quindi, in qualche modo sembra che Eval sia in grado di cercare i valori delle proprietà per nome su DataRow.

Ecco la classe personalizzata

public class Datum: IDictionary<string, object> 
{ 
    private Dictionary<string, object> _entries; 

    public Datum() 
    { 
     _entries = new Dictionary<string, object>(); 
    } 

    public object this[string s] 
    { 
     get 
     { 
      return this._entries[s]; 
     } 
    } 

    ... 
} 

Qui è dove il DataSource viene impostato nelle aspx.cs presentare

rptTags.DataSource = new[] { new Datum { {"Count", 1} }, new Datum { {"Count", 2 } }; 

E qui è il legame nel file aspx

<asp:Repeater ID="rptTags" runat="server"> 
    <ItemTemplate> 
     <%# (int)Eval("Count") > 
    </ItemTemplate> 
</asp:Repeater> 

Utilizzando l'esempio precedente viene visualizzato un errore che indica che la proprietà in questione non esiste, il che è vero, ma è d non esiste nemmeno su DataRow. Come posso farlo legare come System.Data.DataRow?

+0

Potete condividere classe del modello dei dati e l'espressione eval, che avrebbe rendere più facile l'aiuto. –

+0

"Questo rende un incubo provare e testare qualsiasi cosa." Per esempio? –

+0

@mark Ok penso di averlo capito ... – Aristos

risposta

1

Sono venuto stamattina con occhi nuovi e ho trascorso diverse ore a passare attraverso .Net Framework con ILSpy. Sono finalmente riuscito a capire questo enigma e ad attuare una soluzione funzionante. Elencherò le cose che ho appreso che sono pertinenti alla soluzione e quindi dettagliamo la mia implementazione.

  • Quando si associa un DataTable a un ripetitore, ogni RepeaterItem non si associa a un DataRow, come previsto, ma a un DataRowView. Questo in realtà non è importante se non che DataRowView implementa l'interfaccia ICustomTypeDescriptor che è ciò che dobbiamo implementare sulla nostra classe.
  • Anche se il MSDN documentation dice che il metodo Eval utilizza la reflection per eseguire l'associazione tardiva e che l'espressione deve essere valutata su una proprietà pubblica, ciò non è semplicemente vero. L'istruzione Eval utilizza il metodo GetProperties() su ICustomTypeDescriptor per valutare la tua espressione.

Con questo in mente ecco i passaggi che dovevo fare per creare il mio tipo personalizzato che potessi legare dinamicamente proprio come DataTable.

  1. Creare la propria classe personalizzata che eredita da PropertyDescriptor.
  2. Implementare tutti i membri astratti di PropertyDescriptor. Per l'associazione dinamica, la più importante è GetValue(). Qui è dove si definisce come ottenere i valori dalla classe a cui si sta vincolando.
  3. Sulla classe a cui ci si impegna, eredita da CustomTypeDescriptor. Questa è una classe generica che implementa ICustomTypeDescriptor.
  4. Sostituire il metodo GetProperties() di CustomTypeDescriptor e restituire un elenco di PropertyDescriptors (creati nei passaggi 1-2) per ogni valore a cui si desidera essere in grado di eseguire il binding.
  5. Assicurarsi che le proprietà della proprietà abbiano la proprietà Nome impostata. Questa è la proprietà .Net confronta l'espressione di Eval con al fine di determinare quale PropertyDescription utilizzare durante l'associazione.
  6. Impostare l'oggetto CustomTypeDescriptor (creato nei passaggi 3-5) come il DataSource di un WebControl e utilizzare eval() per legare in modo dinamico
0

Un DataSource associabile deve implementare sia IEnumerable o IListSource.

Riguardo all'aspetto dinamico: tenere presente che parte della magia del databinding avviene tramite la riflessione.

+0

Grazie per la risposta. Sì, ho letto nella documentazione MSDN che utilizza la reflection per eseguire l'associazione in ritardo. Tuttavia, DataRow è ancora in grado di cavarsela in qualche modo con il databinding dinamico, quindi mi sento come se dovessi essere in grado di farlo. –

Problemi correlati