СУХОЙ этот метод

Мне нужна помощь, чтобы сделать этот метод универсальным. Это повторяется около десяти раз, чтобы получить списки для различных элементов управления веб-списками (заменяя «MyType» на тип, используемый в конкретном элементе управления).

    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;
    }

Дайте мне знать, если этой информации недостаточно. Думаю, для этого нужны более продвинутые возможности языка, с которыми я только знакомлюсь. Может быть, я должен заставить их всех использовать один и тот же репозиторий?

Спасибо за вашу помощь.

РЕДАКТИРОВАТЬ: Спасибо за вашу помощь. У меня нет поддержки сверстников, поэтому эта доска просто фантастическая, и я чему-то научился у каждого из вас. Хотел бы я принять все ответы.


person Les    schedule 28.05.2009    source источник


Ответы (4)


Сначала вы можете сделать свою функцию немного более краткой, например:

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();
}

На этом этапе большая часть содержимого функции напрямую связана с MyType, поэтому то, как вы можете улучшить ее, во многом зависит от того, как MyType относится к другим задействованным типам. Например, вот гипотетическая версия, которую вы могли бы написать, если бы ваши другие типы следовали разумному (для меня) контракту:

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();
}
person mqp    schedule 28.05.2009
comment
Во-первых, спасибо за то, что сделали метод более кратким; Мне это очень нравится. Все типы наследуют интерфейс IWebControl. Я думаю, что могу заставить их всех использовать один и тот же репозиторий. - person Les; 28.05.2009

Если все типы реализуют один и тот же интерфейс (если они не создают их и обязательно добавляют все свойства интерфейса, которые необходимы в этом методе), вы можете сделать что-то вроде этого:

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();
    }

Еще одно изменение, которое я сделал, — это последняя строка, где у вас есть orderby в отдельной строке и на самом деле никогда не захватывается список Ordered.

EDIT: Чтобы решить проблему с репозиторием, у вас может быть своего рода фабрика репозиториев, которая возвращает правильный репозиторий в зависимости от типа T:

public static IMyTypeRepository  GetRepository(Type t)
{
   if(t == typeof(Type1))
   {
      return Type1Repository();
   }

   if(t == typeof(Type2))
   {
      return Type2Repository();
   }
   .......
}

Предполагая, конечно, что все ваши репозитории реализуют интерфейс IMyRepository.

person BFree    schedule 28.05.2009
comment
Спасибо, что приняли заказ; не зашел так далеко в тестировании. Все типы реализуют один и тот же интерфейс, но используют собственные репозитории. Мне пришлось бы заставить их всех использовать для этого один и тот же репозиторий, да? - person Les; 28.05.2009
comment
Ну, не обязательно. У вас может быть какая-то фабрика, которая создает репозиторий на основе типа T. См. Мое редактирование. - person BFree; 28.05.2009

Прежде всего, все ваши типы должны реализовывать общий interface, который определяет такие свойства, как Active, Value...

Кроме того, насколько я могу судить, должен быть интерфейс репозитория для всех репозиториев независимо от MyType, чтобы вы могли использовать такой общий метод. Метод GetAll() должен быть определен в файле 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();
}
person bruno conde    schedule 28.05.2009
comment
Я не могу печатать достаточно быстро. :( Я набирал то же самое, за исключением того, что использовал контейнер IoC для фабрики. - person Mark; 28.05.2009

Предполагая, что репозитории имеют общий интерфейс, проблема с репозиторием должна быть легко решена: добавьте статическую функцию, такую ​​как


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);
}

Это потребует от вас наименьшего количества изменений в вашем существующем коде, но помните, что в будущем вам придется добавлять поддержку классов для новых репозиториев в эту функцию по мере добавления новых репозиториев в ваш проект (если вы используете модульное тестирование вы легко поймете, забыли ли вы об этом помощнике в любом случае).

person em70    schedule 28.05.2009
comment
Спасибо за эту идею. Я думаю, что в этом случае было бы лучше, чтобы все веб-элементы управления использовали один и тот же репозиторий, тем более что все они взяты из одной и той же таблицы базы данных. - person Les; 28.05.2009