Подтвердить что ты не робот

Включение зависимостей со статическим регистратором, статическим вспомогательным классом

У меня есть статический класс, который вызывает статический класс Logger,

например

static class DoesStuffStatic
{
  public static void DoStuff()
  {
    try
    {
      //something
    }
    catch(Exception e)
    {
      //do stuff; 
      Logger.Log(e);
    }
  }
}

static class Logger
{
  public static void Log(Exception e)
  {
     //do stuff here
  }
}

Как я вставляю Logger в мой статический класс?

Примечание. Я прочитал Injection Dependency в .NET с примерами?, но это, похоже, использует регистратор экземпляров.

4b9b3361

Ответ 1

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

Ответ 2

Это не обязательно так. Пока ваш статический логгер предоставляет метод для:

  • Инъекция классов, которые вы хотите ввести, или
  • Инъекция контейнера DI в соответствующем вызове метода перед его запуском (скажем, что-то вроде метода asp.net global.asax Application_Start), тогда вы должны быть в порядке.

Вот пример. Возьмем следующий класс для DI:

 public class Logger : ILogger
    {
        public void Log(string stringToLog)
        {
           Console.WriteLine(stringToLog);
        }
    }

    public interface ILogger
    {
        void Log(string stringToLog);
    }

И вот наш статический класс, который нуждается в регистраторе:

public static class SomeStaticClass
    {
        private static IKernel _diContainer;
        private static ILogger _logger;

        public static void Init(IKernel dIcontainer)
        {
            _diContainer = dIcontainer;
            _logger = _diContainer.Get<ILogger>();
        }


        public static void Log(string stringToLog)
        {
            _logger.Log(stringToLog);
        }


    }

Теперь, при глобальном запуске вашего приложения (в данном случае, в my global.asax.cs), вы можете создать экземпляр своего контейнера DI, а затем передать его в свой статический класс.

public class Global : Ninject.Web.NinjectHttpApplication
    {

        protected override IKernel CreateKernel()
        {
            return Container;
        }


        static IKernel Container
        {
            get
            {
                var standardKernel = new StandardKernel();
                standardKernel.Bind<ILogger>().To<Logger>();
                return standardKernel;
            }

        }

        void Application_Start(object sender, EventArgs e)
        {
            SomeStaticClass.Init(Container);
            SomeStaticClass.Log("Dependency Injection with Statics is totally possible");

        }

И престо! Теперь вы работаете с DI в своих статических классах.

Надеюсь, что это поможет кому-то. Я перерабатываю приложение, которое использует LOT статических классов, и мы использовали это успешно какое-то время.

Ответ 3

Это очень простой способ "ввести" функциональность статического регистратора.

public static class Logger
{
    private static Action<string, Exception> _logError;
    public static bool Initialised;

    public static void InitLogger(Action<string, Exception, bool> logError)
    {
        if(logError == null) return;
        _logError = logError
        Initialised = true;
    }

    public static void LogError(string msg, Exception e = null)
    {
        if (_logError != null)
        {
            try
            {
                _logError.Invoke(msg, e);
            }
            catch (Exception){}
        }
        else
        {
            Debug.WriteLine($"LogError() Msg: {msg} Exception: {e}");
        }
    }
}

public class MainViewModel
{
    public MainViewModel()
    {
        //Inject the logger so we can call it globally from anywhere in the project
        Logger.InitLogger(LogError);
    }
    public void LogError(string msg, Exception e = null)
    {
        //Implementation of logger
    }
}

Ответ 4

Я не уверен, как работает Logger, но обычно вы можете использовать RequestService для получения вашего экземпляра. Например, в абстрактном классе:

this.HttpContext.RequestServices.GetService(typeof(YOUR_SERVICE));

Это возможно для контроллера, где вы можете получить доступ к HttpContext.

Второй способ - использовать его, например, в Startup, где вы можете это сделать:

serviceCollection.AddScoped(typeof(ICmsDataContext), typeof(TDbContext));

где serviceCollection - это IServiceCollection в ядре dotnet.

Надеюсь, что это помогло.