2

我使用的是ASP.NET Core,我知道这样的日志记录机制已经由框架提供,但是使用它来说明我的问题。因为我不知道日志类型(因为它存储在数据库中),所以我使用了一种Factory模式来构建Logger类。在ASP.NET中使用依赖注入和工厂模式传递服务

的ILogger合同

Log(string msg) 

随后的LoggerFactory将根据PARAM从DB通过创建一个记录器后返回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 

现在,当我需要使用Logger我要这样做:

public class MyService 
{ 
    private ILogger _logger 
    public MyService() 
    { 
     _logger = LoggerFactory.BuildLogger("myType"); 
    } 

但是,我打算让我的课没有任何insta ntiation,我需要使用构造DI为MyService中,我需要注入在启动时所有的依赖:

services.AddTransient<Contracts.ILogger, LoggerFactory.BuildLogger("param") >(); 

但是这不会工作,这一点,我们需要通过一个具体的实现。 如何使用DI进行这项工作,是否有更好的方法来实现?

+0

一种选择是注入'LoggerFactory',而不是'ILogger'。通过这种方式,您可以获得LoggerFactory,从数据库获取Type并构建您的ILogger。如果你想注射ILogger,你必须知道注射时刻你的ILogger的类型。但是你可能还没有这个信息。 –

+0

您的意思是在MyService构造函数中传递LoggerFactory,并且不要将其添加到.net核心服务 – Coding

+0

是的。像这样:'services.AddSingleton ();'。 Singleton意味着你只会在第一次需要的时候创建一个LoggerFactory对象。在此之后,您将只使用相同的。然后,像这样使用:'public MyService(LoggerFactory loggerFactory){....}' –

回答

3

有一对夫妇在你的方法错误:

相反,你的服务应如下所示:

public class MyService 
{ 
    private ILogger _logger; 
    public MyService(ILogger logger) 
    { 
     _logger = logger; 
    } 
} 

这大大简化了依靠​​所有消费者。这也意味着获得​​MyService成为Composition Root的责任,这是获得这些知识的正确位置。

但这意味着您可能需要从ASP.NET Core的内置DI容器转移到更多功能丰富的DI库,因为内置容器无法进行上下文感知注册对于​​,同时让库自动连接其他构造函数依赖关系。

使用ASP.NET Core DI容器,您只能使用代理手动连接您的服务。例如:

services.AddTransient<MyService>(c => new MyService(
    BuildLogger(typeof(MyService).Name), 
    c.GetRequiredService<ISomeOtherDependency>(), 
    c.GetRequiredService<IYetAnotherOne>()); 
+0

Steven,用你的例子,他不能注入正确的ILogger,对吧?如果他在实例化'MyService'之前知道类型,那么他可以将构造函数更改为'public MyService(ILogger logger)'。但由于他不知道,他必须注入一个可以为他做到这一点的界面。如我错了请纠正我。 –

+2

@FabricioKoch:我不知道我跟着你。除此之外,我不建议在这里引入一个通用抽象,因为'MyService'对这个泛型完全不感兴趣;它只是希望登录。因此,成分根源是提供正确类型的问题,而不是消费者。 – Steven

+0

@Steven,我从你那里了解到,这不适用于ASP Core DI容器,因为它不提供组合根目录?如果答案是肯定的,那么如何使用Ninject或AutoFac等其他库? – Coding