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

Я нахожусь в процессе значительных усилий по внедрению 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, который не заставляет меня всегда использовать его для создания экземпляров моих объектов?

1 ответ

Решение

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

http://www.sharpcrafters.com/

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

Другие вопросы по тегам