Итак, я провел много исследований по этому вопросу и не нашел ответов, где я сказал: «Да, ЭТО». Я надеюсь, что вечно эрудированная толпа StackOverflow поможет мне.
Я столкнулся с этой проблемой в нескольких разных сценариях. Скажем, у меня есть приложение на C #, и есть важные вещи, которые я хочу зарегистрировать.
public class MyClass
{
...
public void ImportantMethod()
{
DoInterestingThing();
var result = SomethingElseImportant();
if (result == null)
{
logger.Log("I wasn't expecting that. No biggie.");
return;
}
MoreInterestingStuff();
}
Меня интересует где взять logger
из .
На мой взгляд, у меня есть несколько вариантов.
- Добавьте его в MyClass в конструкторе.
- Получите его, используя глобально доступный сервисный локатор.
- Используйте декораторы методов и AOP, чтобы сделать мою регистрацию для меня.
Ни один из этих вариантов не кажется отличным вариантом. # 3 выглядит невозможным, поскольку я регистрирую прямо в середине своей бизнес-логики, а не просто выполняю простую трассировку своих вызовов методов, входных параметров и / или выданных исключений. № 2, хотя простой кажется, что было бы очень трудно провести модульное тестирование. Конечно, я хотел бы проверить все. # 1, хотя он и работал бы нормально, загромождает всю мою бизнес-логику регистрационными объектами , которые не имеют ничего общего с самими бизнес-объектами.
Есть альтернативные идеи или мысли по поводу одного из вариантов выше?
Большое спасибо!
РЕДАКТИРОВАТЬ: просто чтобы быть ясно, я уже знаю, как сделать DI (я использую Unity), и я уже знаю хорошую структуру ведения журналов (я использую log4net). Просто интересно, как использовать логирование в смысле архитектуры в приложении самым умным способом.
* РЕДАКТИРОВАТЬ *
Я отметил ответ Марка Симана как решение. Я просмотрел свое приложение и обнаружил, что большинство моих вызовов в журнале делали то же самое, что мог сделать декоратор. А именно, зарегистрируйте запись в методе, любые исключенные исключения и выйдите из возвращаемых значений.
В некоторых случаях мне все еще нужно было регистрироваться прямо внутри метода. Примером может быть то, где я хочу быстро потерпеть неудачу в методе, который ничего не возвращает, но не сгенерирует исключение . В этих случаях у меня есть синглтон, который содержит ссылку LogProvider
, которая в свою очередь извлечет именованный экземпляр журнала. Код выглядит примерно так:
private ILog logger = LogProviderFactory.Instance.GetLogger(typeof(Foo));
LogProviderFactory имеет метод SetProvider
, который позволяет заменять синглтон. Итак, в модульном тестировании я могу сделать:
// LogProviderFactory.Instance now is our mock
LogProviderFactory.SetProvider(MockLogProvider);
Декоратор ведения журнала использует тот же LogProvider, что и синглтон (который он получает путем внедрения), поэтому ведение журнала объединяется во всей системе.
Так что на самом деле конечным решением был в основном вариант № 3 и гибрид № 2 (где это шаблон локатора службы, но служба «вводится» в локатор).
АОП
Что касается «аспектно-ориентированного программирования», я был немного разочарован ограничениями языка. Надеемся, что АОП будет рассматриваться как первоклассный гражданин в будущих выпусках.
- Я попробовал PostSharp, но не смог правильно запустить его на моей машине. Кроме того, это было большим ограничением, что вы должны были установить PostSharp в вашей системе, чтобы использовать его (в отличие от простого вызова dll, который поставляется с решением или что-то подобное).
- Я использовал LinFu и смог заставить его работать частично. Однако в нескольких случаях он взорвался. Новый выпуск 2.0 едва документирован, так что это было препятствием.
- Интерфейсный перехват с Unity, однако, кажется, работает хорошо из коробки. Мне повезло, что большинство вещей, которые я хотел записать, были в классах, реализующих интерфейсы.