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.

È stato utile?

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

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