еще раз о log4net и конфиге Unity IOC - PullRequest
5 голосов
/ 24 августа 2009

Я натолкнулся на некоторые из этих вопросов, лежащих на разных сайтах, и l4n officianados, похоже, дает ответы на вопрос об облегченной оболочке, которую log4net 'is' (не так ли?) И тому подобное ошеломляющий факт.

Однако, похоже, что пользователи просят (и это мой вопрос), как вписать модель объекта log4net в последовательность registertype / registerinstance в интерфейсе конфигурации Fluent.

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

бедный ejemplow, я хочу получить ссылку на сконфигурированный экземпляр ILog из метода LogManger.GetLogger и поместить его в свободный поток достаточно рано, чтобы добавить его в свойства моих нижестоящих объектов.

Итак, в ответ на одно нетерпеливое предложение я попытался создать нормальный экземпляр ILog каноническим способом:

log4net.Config.XmlConfigurator.Configure();
static readonly log4Net.Ilog Log = LogManager.GetLogger(thatlongassemblyreflectionstuff);

Так что было бы тривиально (в реальном смысле без усилий) добавить эту ссылку в контейнер Unity и продолжить мою замечательную жизнь.

Однако подпись для метода RegisterInstance требует, чтобы «Тип» не являлся интерфейсом.

Для тех, кто не искал объектную модель log4net, afficiananderos верны: l4n - это «обертка», и вы не можете получить информацию о фактическом «типе» для вещи в журнале.

Так что теперь я должен проверить. И вы знаете, что это значит, это может занять минуту, но, скорее всего, займет час или четыре (сходства, подобные написанию «час» и «четыре», никогда не бывают случайными в реальной жизни).

Однако следующее, за исключением исключенной части о канонической установке, сработало:

container
  .RegisterInstance("Logger", Log, new ContainerControlledLifetimeManager())
.RegisterType<IControllerContext, ControllerContext>
(
   "CtlrCtx", 
   new ContainerControlledLifetimeManager(), 
   new InjectionConstructor(new ResolvedParameter<IMessageBuilder>("MsgBldr")),
   new InjectionProperty("Log",new ResolvedParameter<ILog>("Logger"))
);

Таким образом, хэш-коды для оригинального объекта Log и объекта Log, введенного в свойство моего маленького объекта Context, идентичны.

Однако ...

Процесс внедрения потребовал, чтобы я открыл свойство Log объекта Context через его интерфейс, то есть он больше не мог быть статическим объектом. И то, является ли объект log4net ILog статическим, кажется, решающим фактором относительно того, является ли он сериализуемым и может ли он быть распределен между сборками без драматических предупреждений «время выполнения станет нестабильным» (которые действительно имеют значение только для поклонников матрицы). *

Обескураженный, хотя и не сдерживаемый, я использовал изящную Resharper 'свойство со вспомогательным полем' и установил постоянное поле поддержки, в то время как свойство Interface оставалось нестатичным. Хорошо это построено, и тест побежал зеленый.

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

Так что, возможно, это поможет

Спасибо

Stato

Ответы [ 2 ]

5 голосов
/ 07 февраля 2011

Поможет ли использование InjectionFactory в Unity 2? (см. этот вопрос ). Тогда ваш конфигурационный код будет выглядеть примерно так:

IUnityContainer container = new UnityContainer();
container.RegisterType<ILog>(new InjectionFactory(factory => LogManager.GetLogger()));

Затем вы получаете регистратор с обычным вызовом Resolve ():

ILog logger = container.Resolve<ILog>();
logger.Log(Level.Debug, "Hello world");

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

0 голосов
/ 10 июня 2011
ILog logger = container.Resolve<ILog>();
logger.Log(Level.Debug, "Hello world");

действительно работает.

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

ILog logger = container.Resolve<ILog>();

для каждого класса, что дает мне результат, который кажется лишь незначительно отличным от его реализации в каждом классе ....

Я надеялся, что

private ILog Logger {get;set;} 

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

...