Совет по АОП с С#
У меня есть приложение 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();
}
}