Совет по АОП с С#

У меня есть приложение ASP.NET 3.5 SP1 Webforms. Я использую шаблон MVP (контрольный контроллер) с DI (autofac). Мои ведущие обращаются к контрактам репозитория, определенным в моем домене (DDD), которые реализованы в проекте инфраструктуры.

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

В прошлом я бы добавил еще один параметр к конструкторам Presenter, сохранил ссылку в базовом презентаторе и назвал метод журнала в моих блоках Catch. Мне это не очень нравится, но он выполняет свою работу.

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

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

Из копания, которое я сделал, похоже, что существует 4 основных фреймворка для АОП в .NET.

  • Замок Виндзор - я остался в стороне от этого вообще, потому что он делает много вещей, которые мне действительно не нужны.
  • Spring.net - похоже, что у него хороший послужной список, но вызывает страх благодаря его конфигурации xml (мне не нравятся нечеткие конфигурации).
  • PostSharp - Приведенный атрибут (мне это нравится), но в какой-то момент имел некоторые номера номеров строк, не уверен, что они все еще существуют
  • Единство - множество вещей, которые мне действительно не нужны.

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

Для справки я выбрал Autofac для DI, потому что его беглое, простое в использовании, не могло найти никаких негативных комментариев об этом, и оно просто работает.

Есть ли рекомендации, по которым я должен попытаться использовать структуру AOP? Спасибо, что прочитали все это и добавили какие-то мысли.

Ответ 1

Короткий ответ, для простоты и простоты использования, вы действительно не ошибетесь в PostSharp.

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

Если вам нужны аспекты, которые должны измениться в зависимости от контекста, рассмотрите Spring.NET(или любую инфраструктуру aop, которая внедряет код во время выполнения на основе конфигурации). Это позволяет настраивать поведение ваших объектов в зависимости от того, что вы делаете. Например, через вашу конфигурацию вы можете использовать один тип ведения журнала в консольном приложении, а другой - в веб-приложении. Обратите внимание, что Spring также является контейнером DI (и несколькими другими вещами) - он выходит далеко за пределы AOP, и определенно стоит изучить, как его использовать.

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

Что вы делаете, я рекомендую вам начать с PostSharp.

Ответ 2

Я использую PostSharp в течение некоторого времени, и я должен сказать, что мне нравится простота использования и простота реализации.

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

Ответ 3

Для простых аспектных сценариев я передал тело метода как блок для общего метода, который обрабатывает аспект, то есть реализует "отверстие в средний" шаблон дизайна.

Пример:

public class Class
{
    public void MethodWithoutAspect()
    {
        var dummy = new string('a', 10);

        Console.WriteLine(dummy);
    }

    public void MethodWithAspect()
    {
        Aspect.LogException(() =>
        {
            var dummy = new string('a', 10);

            Console.WriteLine(dummy);
        });
    }
}

public static class Aspect
{
    public static void LogException(Action block)
    {
        try
        {
           block();
        }
        catch (Exception e)
        {
            Log(e);
            throw;
        }
    }

    private static void Log(Exception e)
    {
        throw new NotImplementedException();
    }
}