Как внедрить логические реализации Log4Net ILog с использованием Unity 2.0
В конечном счете это связано с настройкой log4Net, но в общем случае проблема не связана с конкретным протоколом.
В общем, я пытаюсь понять, как это сделать в Microsoft Unity 2.0, что-то эквивалентное тому, что получается с помощью Castle.Facilities.Logging.LoggingFacility. А именно, способность объявлять зависимость от регистратора и инициализировать логгер с типом объекта, в который он вводится.
В духе теста стоит тысяча слов, вот что мне нужно:
class Logger_IOC_Tests
{
//[Test]
public void Logger_should_be_initialized_with_the_type_of_the_object_that_is_using_it()
{
var container = new UnityContainer();
/* Configuration Magic probably involiving registering either
* a custom IDependencyResolverPolicy or BuilderStrategy
* goes here...
*/
container.RegisterType<LoggerUser>(new ContainerControlledLifetimeManager());
var user = container.Resolve<LoggerUser>();
Assert.True(user.Logger.GetUserType() == user.GetType());
}
}
interface ILogger
{
Type GetUserType();
}
class Logger : ILogger
{
private readonly Type _type;
public Logger(Type type)
{
_type = type;
}
public Type GetUserType()
{
return _type;
}
}
class LoggerUser
{
public readonly ILogger Logger;
public LoggerUser(ILogger logger)
{
Logger = logger;
}
}
Ответы
Ответ 1
Я не знаю, если это то, что вы ищете, но я видел это несколько месяцев назад, и мне напомнили об этом, когда я увидел ваш вопрос. Я не использовал Unity, поэтому я не могу сравнить то, что вы разместили, с тем, что находится по ссылке. Надеюсь, вам это будет полезно:
http://davidkeaveny.blogspot.com/2011/03/unity-and-log4net.html
Ответ 2
Я пытаюсь добиться того же результата, что и возможность вставлять правильно настроенные экземпляры ILog
в зависимость, используя инъекцию конструктора с Unity.
В конце концов, я написал собственное расширение единства "log4net", чтобы сделать именно это (частично вдохновленный сообщением в блоге, которое написал другой ответчик, Кеннет Балтринич).
Это позволяет вам зарегистрировать расширение один раз с помощью Unity:
var container = new UnityContainer();
container.AddNewExtension<Log4NetExtension>();
а затем введите правильный экземпляр регистратора ILog:
public class MyClass
{
private readonly ILog logger;
public MyClass(ILog logger)
{
this.logger = logger;
}
}
Расширение можно найти здесь:
https://github.com/roblevine/UnityLoggingExtensions
Дополнительная информация здесь: http://blog.roblevine.co.uk/net/using-log4net-with-unity/
EDIT теперь доступен как пакет NuGet
Ответ 3
После нескольких часов работы в исходном коде Unity я придумал следующее решение. Тем не менее, я бы предпочел найти способ установки соответствующего зависимого преобразователя на основе разрешаемого типа, а не переопределения политики селектора конструктора по умолчанию. Во-первых, поскольку я ранее переопределял селектор конструктора по умолчанию для других целей. В другом случае это решение обрабатывает только зависимости, которые вводятся через конструктор. Для полного охвата нужно было бы переопределить свойства и методы выбора по умолчанию, как я полагаю. Для себя мне нужны только конструкторы.
class Logger_IOC_Tests
{
[Test]
public void Logger_should_be_initialized_with_the_type_of_the_object_that_is_using_it()
{
var container = new UnityContainer();
container.AddNewExtension<LoggingExtension>();
container.RegisterType<LoggerUser>(new ContainerControlledLifetimeManager());
var user = container.Resolve<LoggerUser>();
Assert.True(user.Logger.GetUserType() == user.GetType());
}
}
class LoggingExtension : UnityContainerExtension
{
protected override void Initialize()
{
Context.Policies.SetDefault(typeof(IConstructorSelectorPolicy), new LoggingConstructorSelectorPolicy());
}
}
public class LoggingConstructorSelectorPolicy : DefaultUnityConstructorSelectorPolicy
{
protected override IDependencyResolverPolicy CreateResolver(ParameterInfo parameter)
{
return parameter.ParameterType == typeof(ILogger)
? new LoggerResolverPolicy(parameter.Member.DeclaringType)
: base.CreateResolver(parameter);
}
}
class LoggerResolverPolicy : IDependencyResolverPolicy
{
private readonly Type _dependantType;
public LoggerResolverPolicy(Type dependantType)
{
_dependantType = dependantType;
}
public object Resolve(IBuilderContext context)
{
return new Logger(_dependantType);
}
}
Ответ 4
Вышеупомянутое расширение работает хорошо, но для пользователей MVC5 требуется больше информации о конфигурации. Вот шаги, использующие единство.
Добавьте следующую строку вверху вашего класса startup.cs над пространством имен.
[сборка: log4net.Config.XmlConfigurator(ConfigFile = "Web.config", Watch = true)]
В вашем методе global.asax application_startup
добавьте следующую информацию:
log4net.Config.XmlConfigurator.Configure(new FileInfo(Server.MapPath("~/Web.config")));
Остальная конфигурация контейнера единства должна быть такой:
container.AddNewExtension<Log4NetExtension>();
Убедитесь, что у вас есть appender
, добавленный в ваш web.config. Это должно быть связано с тем, чтобы это правильно работало. Удачи