2010-05-21 9 views
9

Ho un metodo che conta il numero di contatti ogni fornitore, cliente e produttore ha (questo è uno scenario di provare rendere spiegazione più facile!)C# accedere alle proprietà di un oggetto generico

I modelli sono tutti creati da Classi da Linq a SQL. Ogni fornitore, cliente e produttore possono avere uno o più contatti

public int CountContacts<TModel>(TModel entity) where TModel : class 
{ 
    return entity.Contacts.Count(); 
} 

È possibile che questo ovviamente non funziona, perché il 'soggetto' è generico e non sa se ha la proprietà 'Contatti'. Qualcuno può aiutare con come ottenere questo?

risposta

6

Un modo semplice sarebbe quello di collegare un'interfaccia alle classi implementate nel generico.

public int CountContacts<TModel>(TModel entity) where TModel : IContacts 


interface IContacts 
{ 
    IList<Contact> Contacts {get;} //list,Ilist,ienumerable 
} 
+0

+1 Tranne che non si dovrebbe restituire l'elenco - preferibilmente IList <> o forse anche IEnumerable <> – n8wrl

+0

Buon punto. Stavo digitando velocemente e non ci ho pensato. – kemiller2002

+0

Il problema è che le classi LINQ a SQL utilizzano EntitySet per tale scopo e la proprietà Contacts con il tipo EntitySet non implementerà la proprietà dell'interfaccia, quindi dovrà implementarla manualmente in ogni classe. – Venemo

3

Un modo per imporre un contratto di dove fornitori, clienti e manufactors devono contenere una proprietà Contacts è con le interfacce. Fare ogni entità implementare un'interfaccia che contiene la proprietà Contacts:

interface IContactable 
{ 
    IEnumerable<Contact> Contacts {get;} 
} 


public int CountContacts<TModel>(TModel entity) where TModel : class, IContactable 
{ 
    return entity.Contacts.Count(); 
} 
0

Un altro modo è quello di creare un'interfaccia solo per il conteggio. Puoi chiamarlo ICountable.

Da MSDN

public interface ICountable<out T> 
{ 
    int Count{ get; } 
} 
public class MyCollection : ICountable<string>, ICountable<FileStream> 
{ 
    int ICountable<string>.Count 
    { 
     get { return 1; } 
    } 
    int ICountable<FileStream>.Count 
    { 
     get { return 2; } 
    } 
} 
1

Tutte le risposte finora sono corrette, ma dovrebbe anche sottolineare che il motivo per il codice non viene compilato è perché i tipi tModel non hanno nulla in comune. Specificando una comune classe base o un'interfaccia, tutti implementano con la proprietà 'Contatti' il tuo codice funzionerà.

0

Esistono diverse soluzioni al problema.

  • Eredita la stessa classe astratta o implementa la stessa interfaccia con le entità. (Gli altri hanno esaurito ogni possibile soluzione con questo.)
  • Se si utilizza .NET 4, la parola chiave dynamic potrebbe essere la soluzione più economica.

Ad esempio:

public int CountContacts(dynamic entity) 
{ 
    return entity.Contacts.Count(); 
} 

Ciò significa che entity valutazione non sarà garantito fino al runtime, e se vi capita di chiamare il metodo su un oggetto che non dispone di una proprietà Contacts, si getterà tu un'eccezione.

Problemi correlati