1

Я реализовал шаблон хранилища с незнанием персистентности. Реализация хранилища взаимодействует только с объектами сущности, IUnitOfWork и ITable<T> интерфейсами. Предполагается, что IUnitOfWork не используется повторно, а представляет собой одну транзакцию. До сих пор я реализовал как в памяти, так и в Linq-to-Sql версии IUnitOfWork и ITable<T>.Какой шаблон дизайна для поиска моего IUnitOfWork?

Моя проблема заключается в том, что из-за ввода в репозиторий IUnitOfWork я в конечном итоге нуждаюсь в том, чтобы знать, как создать экземпляр нового IUnitOfWork, где используется репозиторий. Поскольку это основная часть, которая должна быть подключаемой, кажется, что я сделал что-то неправильно. Общая схема использования что-то вроде этого:

FooUnitOfWork unitOfWork = new FooUnitOfWork(); 
Repository repos = new Repository(unitOfWork); 
// ...act upon repos 
unitOfWork.Save(); 

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

Что является наиболее подходящим шаблоном для этого? Я посмотрел на Fowler's discussion on the topic, но ни один из его примеров не выглядит чистым. Я уже чувствую, что объем абстракции, который у меня есть, больше, чем мне хотелось бы, чтобы создать еще одну косвенность, кажется чрезмерной.

В настоящий момент я склоняюсь к своему провайдеру приложений, который можно настроить для получения правильного IUnitOfWork. Я вне базы или это то, что нужно, чтобы по-настоящему быть агностиком реализации?

+0

Ну, вам нужен контекст для связывания единицы работы с (например, потоком или httpcontext), тогда вам нужно использовать фабричный метод для получения единицы работы (vs new()). – meandmycode

+0

Статический заводский метод (с поддержкой контекста потока) будет чистым интерфейсом для создания экземпляра. Как насчет настройки конфигурации (контекст БД и т. Д.), Которые я сейчас устанавливаю в конструкторах 'UnitOfWork'? – mckamey

+0

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

ответ

1

Обновление: В то время как это действительно не сломалось, это привело к созданию контейнера IoC для бедных людей. Я в конечном итоге просто заменить все эти:

UnitOfWorkFactory.Create(); 

с обобщенным Common Service Locator реализации:

Microsoft.Practices.ServiceLocation.ServiceLocator.Current.GetInstance<IUnitOfWork>(); 

Это позволило мне создать библиотеку, которая использует Dependency Injection, не вынуждая всех пользователей использовать ту же структуру IoC ,

Возможно, я должен использовать очень простую фабрику, где я могу установить обратный вызов? На нем может быть множество статических методов:

public static class UnitOfWorkFactory 
{ 
    private static Func<IUnitOfWork> FactoryMethod; 

    public static IUnitOfWork Create() 
    { 
     if (UnitOfWorkFactory.FactoryMethod == null) 
     { 
      throw new InvalidOperationException("..."); 
     } 

     return UnitOfWorkFactory.FactoryMethod(); 
    } 

    public static void SetFactoryMethod(Func<IUnitOfWork> factory) 
    { 
     UnitOfWorkFactory.FactoryMethod = factory; 
    } 
} 

Где это ломается?

+0

Поскольку не было лучшего решения, я думаю, что я катаюсь с этим. Мне все равно хотелось бы услышать, где это ломается, или если у кого-то другая перспектива. – mckamey

0

Я бы предложил использовать шаблон Vistor, чтобы обнаружить реализации интерфейса IUnitOfWork.

[UnitOfWork(Name="foo")] 
public class FooUnitOfWork : IUnitOfWork {} 

Repository repo = new Repository("foo"); 
//stuff happens 
repo.Save(); //or repo.Worker.Save(); 

Внутри экземпляра репо фабрика обнаружения находит работника и создает его.

+0

Я не вижу, как это облегчает определение *, которое * 'IUnitOfWork' я хочу. Код, который его использует, будет одинаковым для всех реализаций, иначе я просто создам экземпляр 'IUnitOfWork', который я хочу. – mckamey

+0

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

+0

Нет ничего, что можно было бы отключить. Каждое инстанцирование в логике точно такое же (например, ваш пример без перехода в «foo»), потому что на уровне конфигурации на уровне приложения выбран механизм хранения. Это гораздо больше похоже на модель поставщика ASP.NET. – mckamey