Декорирование цепочек репозиториев и специализированных репозиториев с внедрением зависимости - PullRequest
1 голос
/ 13 января 2009

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

Предположим, у меня есть интерфейс, который называется IRepository.

 public interface IRepository<T>
 {
    T Get(int id);
    void Add(T value);
    void Update(T value);
    void Delete(T value);
    ...
 }

И предположим, у меня есть реализация, подобная

public class NHibernateRepository<T>
{
    ...
}

Теперь все хорошо, я могу выполнять все свои основные операции с хранилищем для поддержки всех функций CRUD, но я могу захотеть специализированных операций, поэтому предположим, что у меня есть такой интерфейс:

public interface IUserRepository : IRepository<User>
{
     IList<User> GetUsersByRole(Role role);
}

И такая реализация:

public class UserRepository : NHibernateRepository<User>, IUserRepository
{
    ....
}

Хорошо, это базовая настройка, теперь я хочу сделать еще одну вещь. Я хочу, чтобы логирование и транзакции и тому подобное были прозрачными. Поэтому я хотел бы использовать среду внедрения зависимостей, такую ​​как Castle Windsor или StructureMap, чтобы при запросе IRepository он был обернут в LoggingRepository и TransactionRepository, которые оба реализуют IRepository.

Итак, я хочу сделать что-то вроде этого:

IUserRepository repository = container.Resolve< IUserRepository>();

и пусть он вернет пользовательский репозиторий, завернутый в декораторы Logging и Transaction, но я не могу придумать, как это сработает. Единственный способ заставить это работать - реализовать UserRepository, например:

public class UserRepository : DecoratorRepository<T>, IUserRepository
{
    protected IRepository<T> Repository { get; set; }

    public UserRepository(IRepository<T> innerRepository)
    {
        Repository = innerRepository;
    }
}

Это будет означать, что мы будем использовать Dependancy Injection, чтобы создать декорированный репозиторий и передать его в конструктор UserRepository, а затем использовать его в качестве репозитория, в котором мы выполняем операции. Это будет работать, но я все еще не думаю, что это идеально.

Итак, мой вопрос в том, прав ли я, что это единственный способ сделать это, или я не понимаю это правильно или просто что-то упускаю все вместе. Кроме того, если вы столкнулись с этой проблемой раньше, как вы решили эту проблему?

Ответы [ 3 ]

3 голосов
/ 13 января 2009

Если вы собираетесь использовать декораторы , это звучит правильно. Каждый декоратор должен иметь конструктор с аргументом IRepository и вызывать код регистрации или транзакции вокруг вызовов внутреннего репозитория, который он декорирует.

В качестве альтернативы вы можете рассмотреть, но у меня очень мало опыта в аспектно-ориентированном программировании. В этом сценарии вы применяете атрибуты к своим классам, которые указывают, какие методы ведения журнала или транзакции вы хотите использовать. В какой-то момент эти методы встраиваются в ваш код, это можно сделать как в качестве дополнительного шага компиляции, так и в случае SpringFramework.net во время внедрения.

1 голос
/ 13 января 2009

Этот блог выглядит как решение вашей проблемы. Это в основном тот же дизайн, за исключением того, что вместо защищенного IRepository вы делаете его закрытым только для чтения.

1 голос
/ 13 января 2009

Не могли бы вы иметь абстрактный базовый класс LoggingRepository, который бы обрабатывал ведение журналов для ваших различных Get, Add, Update, Delete, делал их виртуальными и потом наследовал от них?

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

...