Стоит ли перехват создаваемых им накладных расходов?

#unity-container #aop #unity-interception

#unity-контейнер #aop #unity-перехват

Вопрос:

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

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

 class SomeService
{
    [Transaction]
    public void DoSomething(CustomerId id)
    {
        Customer c = CustomerRepository.LoadCustomer(id);
        c.DoSomething();
    }
}
  

и [Transaction] обработчик позаботится о создании сеанса и транзакции, фиксации транзакции (или откате исключения) и т.д.

Я обеспокоен тем, что использование такого рода перехвата привяжет меня к использованию Unity практически везде в коде. Если я введу аспекты таким образом, то я никогда не должен вызывать new SomeService() , или я получу службу, у которой нет транзакций. Хотя это приемлемо в производственном коде, в тестах это кажется слишком большими накладными расходами. Например, мне пришлось бы преобразовать это:

 void TestMethod()
{
    MockDependency dependency = new MockDependency();
    dependency.SetupForTest();
    var service = SomeService(dependency);
    service.DoSomething();
}
  

в это:

 void TestMethod()
{
    unityContainer.RegisterType<MockDependency>();
    unityContainer.RegisterType<IDependency, MockDependency>();

    MockDependency dependency = unityContainer.Resolve<MockDependency>();
    dependency.SetupForTest();
    var service = unityContainer.Resolve<SomeService>();
    service.DoSomething();
}
  

Это добавляет 2 строки для каждого используемого мной макетного объекта, что приводит к довольно большому объему кода (в наших тестах используется много макетов с отслеживанием состояния, поэтому нередко в тестовом классе бывает 5-8 макетных объектов, а иногда и больше.)

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

Теперь, если я откажусь от использования перехвата, я получу:

 class SomeService
{
    public void DoSomething(CustomerId id)
    {
        Transaction.Run(
            () => {
                Customer c = CustomerRepository.LoadCustomer(id);
                c.DoSomething();
             });
    }
}
  

что, по общему признанию, не так приятно, но и не кажется таким уж плохим.

Я даже могу настроить перехват моего собственного бедняка:

 class SomeService
{
    [Transaction]
    public void DoSomething(CustomerId id)
    {
        Interceptor.Intercept(
            MethodInfo.GetCurrentMethod(),
            () => {
                Customer c = CustomerRepository.LoadCustomer(id);
                c.DoSomething();
             });
    }
}
  

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

Есть ли лучший способ использования Unity interception, который не заставляет меня всегда использовать его для создания экземпляров моих объектов?

Комментарии:

1. @Mat, я бы с этим не согласился. Я вижу некоторое сходство между этим и некоторыми примерами «о чем не спрашивать», это все еще хорошо написанный и обоснованный вопрос. Он не спрашивает «Какой наш любимый инструмент AOP», а говорит «Я рассматриваю возможность использования Unity, но у меня есть некоторые опасения, какой опыт у людей от его использования может помочь мне решить, стоит ли это». Возможно, это погранично, но ИМО это достаточно хорошо, чтобы иметь достоинства и не быть закрытым.

2. @Mat Вопрос касается конкретной проблемы, которую я испытываю при использовании Unity, а не общего вопроса о том, стоит ли AOP. Я отредактировал последнюю строку вопроса, чтобы отразить это.

Ответ №1:

Если вы хотите использовать AOP, но беспокоитесь о Unity, я бы порекомендовал вам проверить PostSharp. Это реализует AOP как проверку после компиляции, но не вносит изменений в то, как вы используете код во время выполнения.

http://www.sharpcrafters.com/

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