Hus*_*man 4 c# asp.net-mvc dependency-injection factory-pattern asp.net-core
我正在使用ASP.NET Core,我知道框架已经提供了这样的Logging机制,但是使用它来说明我的问题.
我正在使用一种Factory模式来构建Logger类,因为我不知道日志记录的类型(因为它存储在DB中).
ILogger合同
Log(string msg)
Run Code Online (Sandbox Code Playgroud)
然后,在根据从DB传递的参数创建Logger之后,LoggerFactory将返回ILogger:
public class LoggerFactory
{
public static Contracts.ILogger BuildLogger(LogType type)
{
return GetLogger(type);
}
//other code is omitted, GetLogger will return an implementation of the related logger
Run Code Online (Sandbox Code Playgroud)
现在,当我需要使用Logger时,我必须这样做:
public class MyService
{
private ILogger _logger
public MyService()
{
_logger = LoggerFactory.BuildLogger("myType");
}
Run Code Online (Sandbox Code Playgroud)
但是,我打算在没有任何实例化的情况下保留我的类,我需要在MyService中使用Constructor DI,我需要在Startup上注入所有依赖项:
services.AddTransient<Contracts.ILogger, LoggerFactory.BuildLogger("param") > ();
Run Code Online (Sandbox Code Playgroud)
但这不起作用,我们需要通过一个具体的实现.如何使用DI来完成这项工作,是否有更好的方法来实现它?
Ste*_*ven 16
您的方法中存在一些错误:
LoggerFactory
类型,即违反依赖性反转原则.ILogger
即消费者所依赖的真实服务.这使得系统更难以测试,更难以维护,并使对象图分析变得复杂.相反,您的服务应如下所示:
public class MyService
{
private ILogger _logger;
public MyService(ILogger logger)
{
_logger = logger;
}
}
Run Code Online (Sandbox Code Playgroud)
这大大简化了所有依赖的消费者ILogger
.这也意味着,获得正确ILogger
的MyService
成为的责任组成的根,这是有这方面的知识的正确位置.
然而,这确实意味着你可能需要从移开内置ASP.NET核心的功能更丰富DI库DI容器,因为内置容器不能够使上下文感知登记的ILogger
,同时具有库自动连接其他构造函数依赖项.
使用ASP.NET Core DI容器,您只能使用委托手动连接服务.例如:
services.AddTransient<MyService>(c => new MyService(
BuildLogger(typeof(MyService).Name),
c.GetRequiredService<ISomeOtherDependency>(),
c.GetRequiredService<IYetAnotherOne>());
Run Code Online (Sandbox Code Playgroud)