Как внедрить реализации LogogNet ILog с использованием Unity 2.0 - PullRequest
19 голосов
/ 27 июля 2011

В конечном счете, это связано с настройкой 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;
    }
}

Ответы [ 6 ]

14 голосов
/ 28 июля 2011

Я не знаю, если это то, что вы ищете, но я видел это несколько месяцев назад и мне напомнили об этом, когда я увидел ваш вопрос.Я не использовал Unity, поэтому я не могу сравнить то, что вы опубликовали, с тем, что находится по ссылке.Надеюсь, вам будет полезно:

http://davidkeaveny.blogspot.com/2011/03/unity-and-log4net.html

9 голосов
/ 28 декабря 2012

Я пытался добиться того же результата, что смог вставить правильно сконфигурированные 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/

РЕДАКТИРОВАТЬ теперь доступно в виде пакета NuGet

4 голосов
/ 27 июля 2011

После нескольких часов копания в исходном коде 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);
    }
}
2 голосов
/ 08 февраля 2016

Вышеприведенное расширение работает хорошо, но для пользователей 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")));

Остальная конфигурация для контейнера Unity должна быть такой:

container.AddNewExtension<Log4NetExtension>();

Убедитесь, что вы добавили appender в ваш файл web.config. Это должно быть об этом, чтобы заставить это работать правильно. Удачи

1 голос
/ 06 августа 2018

С Unity 5 и выше вы можете теперь использовать собственное расширение Unity Log4Net от https://github.com/unitycontainer/log4net.

Все, что вам нужно сделать, это установить Nuget и добавить расширение в ваш контейнер:

container.AddNewExtension<Log4NetExtension>();

И он будет работать автоматически с любыми классами, которые используют ILog в качестве зависимости.

0 голосов
/ 15 ноября 2018

Вы можете использовать следующий код для ввода Log4Net

log4net.Config.BasicConfigurator.Configure();    

container.RegisterType<ILog>(new InjectionFactory(x => LogManager.GetLogger(typeof(Program))));

typeof (Программа) используется, так как я регистрируюсь в классе программы. Используйте можете использовать имя класса или это ключевое слово

Затем вы можете ввести ILog в класс

 public class MyClass
 {
   private readonly ILog logger;

   public MyClass(ILog logger)
   {
     this.logger = logger;
   }
 }
...