Domanda
Ho bisogno di aiuto rendendo questo metodo generico. Si è ripetuto una decina di volte per ottenere liste per diversi controlli elenco web (sostituendo "MyType" per il tipo utilizzato nel particolare di controllo).
private static IList<MyType> GetList(RequestForm form)
{
// get base list
IMyTypeRepository myTypeRepository = new MyTypeRepository(new HybridSessionBuilder());
IList<MyType> myTypes = myTypeRepository.GetAll();
// create results list
IList<MyType> result = new List<MyType>();
// iterate for active + used list items
foreach (MyType myType in myTypes)
{
if (myType.Active || form.SolutionType.Contains(myType.Value))
{
result.Add(myType);
}
}
// return sorted results
result.OrderBy(o => o.DisplayOrder);
return result;
}
Vorrei sapere se questo non è abbastanza informazioni. Penso che questo richiede più caratteristiche del linguaggio avanzate che sto solo acquisire familiarità con. Forse dovrei farli tutti utilizzano lo stesso repository?
Grazie per il vostro aiuto.
EDIT: Grazie per l'aiuto. Non ho alcun supporto tra pari, quindi questa scheda è fantastico e ho imparato qualcosa da ciascuno di voi. Vorrei poter accettare tutte le risposte.
Soluzione
Si potrebbe in primo luogo rendere la vostra funzione di un po 'più concisa in questo modo:
private static IList<MyType> GetList(RequestForm form)
{
// get base list
IMyTypeRepository myTypeRepository =
new MyTypeRepository(new HybridSessionBuilder());
IList<MyType> myTypes = myTypeRepository.GetAll();
return myTypes.Where(x => x.Active || form.SolutionType.Contains(x.Value))
.OrderBy(x => x.DisplayOrder).ToList();
}
A quel punto, la maggior parte dei contenuti della funzione è direttamente correlata al MyType
, così come è possibile migliorare ulteriormente dipende in gran parte da come MyType
riferisce agli altri tipi coinvolti. Ad esempio, ecco un ipotetica versione che si potrebbe scrivere se le altre tipologie hanno seguito un contratto ragionevole dall'aspetto (per me):
private static IList<T> GetList(RequestForm form) where T : OrderedValueContainer
{
// we'll want to somehow genericize the idea of a TypeRepository that can
// produce these types; if that can't be done, we're probably better off
// passing a repository into this function rather than creating it here
var repository = new TypeRepository<T>(new HybridSessionBuilder());
IList<T> myTypes = repository.GetAll();
// the hypothetical OrderedValueContainer class/interface
// contains definitions for Active, Value, and DisplayOrder
return myTypes.Where(x => x.Active || form.SolutionType.Contains(x.Value))
.OrderBy(x => x.DisplayOrder).ToList();
}
Altri suggerimenti
Se tutti i tipi implementano la stessa interfaccia, (se non poi li fanno, e assicurarsi di aggiungere tutte le proprietà all'interfaccia che sono necessari in questo metodo) allora si può fare qualcosa di simile:
private static IList<T> GetList(RequestForm form)
where T: IMyInterface
{
// get base list
IMyTypeRepository myTypeRepository = new MyTypeRepository(new HybridSessionBuilder());
IList<T> myTypes = myTypeRepository.GetAll();
// create results list
IList<T> result = new List<T>();
// iterate for active + used list items
foreach (T myType in myTypes)
{
if (myType.Active || form.SolutionType.Contains(myType.Value))
{
result.Add(myType);
}
}
// return sorted results
return result.OrderBy(o => o.DisplayOrder).ToList();
}
Un altro cambiamento che ho fatto è l'ultima linea, dove si aveva l'orderby su una linea separata e non sono mai stati realmente cattura l'elenco ordinato.
Modifica Per risolvere il problema repository, si può avere una fabbrica repository di sorta che restituisce il repository corretta in base al tipo di T:
public static IMyTypeRepository GetRepository(Type t)
{
if(t == typeof(Type1))
{
return Type1Repository();
}
if(t == typeof(Type2))
{
return Type2Repository();
}
.......
}
Supponendo, naturalmente, che tutti i repository implementano l'interfaccia IMyRepository.
Prima di tutto, tutti i tipi di devono implementare un interface
comune che definiscono immobili come Active
, Value
...
Inoltre, per quello che posso dire, ci deve essere un'interfaccia repository per tutti i repository indipendentemente dal MyType
in modo che è possibile utilizzare un metodo generico come questo. Il metodo GetAll()
dovrebbe essere definito nel IRepository
.
public interface IRepository<T> where T : IMyType
{
IList<T> GetAll();
}
public class RepositoryFactory
{
public static IRepository<T> createRepository<T>(ISessionBuilder sb) where T : IMyType
{
// create repository
}
}
public interface IMyType
{
bool Active { get; }
string Value { get; }
}
private static IList<T> GetList(RequestForm form) where T : IMyType
{
// get base list
IRepository<T> repository = RepositoryFactory.createRepository<T>(new HybridSessionBuilder());
IList<T> myTypes = repository.GetAll();
// create results list
IList<T> result = new List<T>();
// iterate for active + used list items
foreach (T myType in myTypes)
{
if (myType.Active || form.SolutionType.Contains(myType.Value))
{
result.Add(myType);
}
}
// return sorted results
return result.OrderBy(o => o.DisplayOrder).ToList();
}
Supponendo che i repository condividono un'interfaccia comune, la questione con il repository dovrebbe essere facile da risolvere: aggiungere una funzione statica come
public static IRepository RepositoryForType(Type t)
{
if(t == typeof(SomeClass))
return new SomeClassRepository(new HybridSession());
else if ...
else throw new InvalidOperationException("No repository for type " + t.Name);
}
Questo dovrebbe richiedere il minor numero di modifiche al codice esistente, ma la mente che in futuro si dovrà aggiungere classi supporto per i nuovi depositi in questa funzione quando si aggiungono nuovi repository nel progetto (se siete utilizzando il test delle unità si potrebbero facilmente capire se ti sei dimenticato di questo helper in ogni caso).