Ninject, как внедрить универсальный Logger‹T›, вызвав LoggerFactory.CreateLogger

Я работаю над приложением ASP.NET MVC.

Я инициализировал свой LoggerFactory в статическом классе, который вызывается из Global.asax.

using Microsoft.Extensions.Logging;
using Serilog;
using System.IO;

namespace web
{
    public static class LogConfig
    {
        public static LoggerFactory LoggerFactory = new LoggerFactory();

        public static void RegisterLogger()
        {
            LoggerFactory = new LoggerFactory();
            Log.Logger = new LoggerConfiguration().MinimumLevel.Debug().WriteTo.RollingFile(Path.Combine("", "log-{Date}.txt")).CreateLogger();
            LoggerFactory.AddSerilog();
        }
    }
}

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

В моем конструкторе у меня есть:

private ILogger<MyTypeController> _logger;

public MyTypeController(ILogger<MyTypeController>) 
{
    // This works fine but I want to inject it
    _logger = LogConfig.LoggerFactory.CreateLogger<MyTypeController>();
}

Приведенный выше код работает, но я хочу внедрить его с помощью ninject... это то, что я пробовал, но даже не компилируется:

kernel.Bind(typeof(ILogger<>)).ToProvider(LogConfig.LoggerFactory.CreateLogger<>());

person Hooman Bahreini    schedule 20.10.2017    source источник
comment
Кросс размещен здесь: github.com/ninject/Ninject/issues/259   -  person BatteryBackupUnit    schedule 20.10.2017
comment
Я бы изменил вопрос и спросил, как внедрить регистратор, созданный как CreateLogger<T>, в аргумент конструктора неуниверсального интерфейса ILogger вместо ILogger<T>. Внедрение ILogger<T> — это просто шум для потребителя, который может привести к случайным ошибкам, когда указан неверный T, и усложняет тестирование.   -  person Steven    schedule 20.10.2017
comment
Спасибо @Steven ... Я могу обновить вопрос. По сути, я пытаюсь воспроизвести то, что происходит в MVC Core, на моем веб-сайте MVC framework. В MVC Core ILoggerFactory и ILogger‹T› вводятся в программу... но здесь мне нужно специально вызвать метод создания LoggerFactory...   -  person Hooman Bahreini    schedule 20.10.2017
comment
Внедрение ILoggerFactory и ILogger<T> — ужасная идея, и, как мне кажется, единственная причина, по которой Microsoft делает это (и публично продвигает это), заключается в том, что в их встроенном контейнере отсутствует возможность сопоставления неуниверсального интерфейса с универсальной реализацией. Другими словами, они продвигают плохие методы из-за отсутствия реализации.   -  person Steven    schedule 20.10.2017
comment
Еще раз спасибо @Steven ... Так что мне делать? Мне в основном не нужна фабрика регистраторов, я использую Serilog, я просто хочу инициализировать Serilog один раз при запуске приложения и внедрить его в классы для ведения журнала. Я думал, что использование LoggerFactory - хорошая идея, потому что я могу менять поставщиков... но я действительно новичок в этом... Я был бы очень признателен, если бы вы дали мне немного больше деталей, что было бы лучшим подходом? Я полностью счастлив изменить подход.   -  person Hooman Bahreini    schedule 20.10.2017
comment
У меня нет ответа на ваш вопрос; У меня нет такого опыта работы с Ninject. Будут другие, которые смогут помочь вам в этом. Я могу помочь с правильным вопросом :)   -  person Steven    schedule 20.10.2017
comment
Во-первых, исправьте свой образец, который, как вы утверждаете, работает. Вы даже не указываете имя параметра. Во-вторых, добавьте исключение компиляции, которое препятствует его компиляции: не просто ссылайтесь на него и не предоставляйте его.   -  person Brett Caswell    schedule 05.11.2017
comment
@Brett, Create Logger имеет несколько переопределений, это правильное использование: ILogger‹Foo› foo = factory.CreateLogger‹Foo›(); Если вы читали мой последний комментарий, я сказал, что код для последнего примера даже не компилируется, поэтому я прошу правильный синтаксис - исключений нет.   -  person Hooman Bahreini    schedule 05.11.2017


Ответы (2)


Я делаю следующее с NLog, но это также может работать с Ninject:

var createLoggerMethod =
    typeof(LoggerFactoryExtensions).GetMethod(nameof(LoggerFactoryExtensions.CreateLogger),
        new[] {typeof(ILoggerFactory)});
kernel.Bind(typeof(ILogger<>)).ToMethod(context =>
{
    var createLoggerGeneric = createLoggerMethod.MakeGenericMethod(context.GenericArguments);
    var logger = createLoggerGeneric.Invoke(null, new []{ loggerFactory });
    return logger;
});
person oeaoaueaa    schedule 11.04.2018

Читая комментарии @Steven, а также читая его блог на Простой инжектор, я понял, что внедрение универсального регистратора ILogger<T> на самом деле не очень хороший подход.

См. этот ответ для более подробной информации.

person Hooman Bahreini    schedule 01.02.2019