C# 使用静态记录器、静态助手类进行依赖项注入

C# 使用静态记录器、静态助手类进行依赖项注入,c#,unit-testing,static,dependency-injection,C#,Unit Testing,Static,Dependency Injection,我有一个静态类,它调用一个静态记录器类 e、 g 如何将记录器注入到静态类中 注意:我已经读过了,但这似乎使用了实例记录器。您不能注入静态记录器。您必须将其更改为实例记录器(如果可以的话),或者将其包装到实例记录器(将调用静态日志)。此外,向静态类注入任何内容都相当困难(因为您不以任何方式控制静态构造函数)——这就是为什么我倾向于将所有要注入的对象作为参数传递。这不一定如此。只要您的静态记录器公开以下方法: 要注入的类的注入,或 在运行DI容器之前(比如在asp.net global.asax

我有一个静态类,它调用一个静态记录器类

e、 g

如何将记录器注入到静态类中


注意:我已经读过了,但这似乎使用了实例记录器。

您不能注入静态记录器。您必须将其更改为实例记录器(如果可以的话),或者将其包装到实例记录器(将调用静态日志)。此外,向静态类注入任何内容都相当困难(因为您不以任何方式控制静态构造函数)——这就是为什么我倾向于将所有要注入的对象作为参数传递。

这不一定如此。只要您的静态记录器公开以下方法:

  • 要注入的类的注入,或
  • 在运行DI容器之前(比如在asp.net global.asax应用程序_Start方法中),在适当的方法调用中注入DI容器,那么您就可以了
这里有一个例子。参加以下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);
        }


    }
公共静态类SomeStaticClass
{
私有静态IKernel_双容器;
专用静态ILogger_记录器;
公共静态void Init(IKernel双容器)
{
_双容器=双容器;
_logger=\u diContainer.Get();
}
公共静态无效日志(字符串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");

        }
公共类全局:Ninject.Web.NinjectHttpApplication
{
受保护的覆盖IKernel CreateKernel()
{
返回容器;
}
静态IKernel容器
{
得到
{
var standardKernel=新的standardKernel();
standardKernel.Bind().To();
返回标准内核;
}
}
无效应用程序\u启动(对象发送方,事件参数e)
{
SomeStaticClass.Init(容器);
Log(“使用Statics进行依赖注入是完全可能的”);
}
现在,您可以在静态类中启动并运行DI了


希望这对其他人有所帮助。我正在处理一个使用大量静态类的应用程序,我们已经成功地使用了一段时间。

我不确定记录器是如何工作的,但通常可以使用RequestService获取实例。例如,在抽象类中:

this.HttpContext.RequestServices.GetService(typeof(YOUR_SERVICE));
对于控制器,您可以访问HttpContext

第二种方法是在Startup中使用它,您可以这样做:

serviceCollection.AddScoped(typeof(ICmsDataContext), typeof(TDbContext));
其中serviceCollection是dotnet Core中的IServiceCollection


希望能有所帮助。

这是一种“注入”静态记录器功能的非常简单的方法

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
    }
}
公共静态类记录器
{
私人静态动作_logError;
公共静态bool初始化;
公共静态void InitLogger(操作日志错误)
{
if(logError==null)返回;
_logError=logError
初始化=真;
}
公共静态无效日志错误(字符串消息,异常e=null)
{
如果(_logError!=null)
{
尝试
{
_logError.Invoke(msg,e);
}
捕获(异常){}
}
其他的
{
WriteLine($“LogError()Msg:{Msg}异常:{e}”);
}
}
}
公共类主视图模型
{
公共主视图模型()
{
//注入记录器,以便我们可以从项目中的任何位置全局调用它
Logger.InitLogger(LogError);
}
public void LogError(字符串消息,异常e=null)
{
//记录器的实现
}
}

在我看来更像是依赖项解析,而不是依赖项注入。静态类现在了解依赖项框架。但不难调整它以避免它。(在应用程序中解析\u启动并使用解析的依赖项初始化,而不是在初始化时提供解析程序。)问题是如何将静态类注入到静态类中。这涉及如何将非静态实例注入到静态类中。这看起来像是对前一个答案中的以下语句的响应:“向静态类注入任何内容也相当困难”对于像记录器这样简单的东西来说,这似乎太复杂了。这是模拟静态类的唯一方法,我只想说,你可以使用静态构造函数,你只是没有能力传递任何构造函数参数,因为这是严格禁止的。
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
    }
}