在ASP.NET中使用依赖注入和工厂模式传递服务 [英] Passing Services using Dependency Injection and Factory Pattern in ASP.NET

查看:151
本文介绍了在ASP.NET中使用依赖注入和工厂模式传递服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用ASP.NET Core,我知道框架已经提供了这种Logging机制,但是用它来说明我的问题.

I am using ASP.NET Core, I know that such Logging mechanism is already provided by the framework, but using this to illustrate my problem.

由于我不知道日志记录的类型(因为它存储在DB中),因此我正在使用某种Factory模式来构建Logger类.

I am using kind of Factory pattern to build the Logger class, since I don't know the type of logging (because it is stored in DB).

ILogger合同

Log(string msg)

然后,基于从数据库传递的参数创建Logger后,LoggerFactory将返回ILogger:

Then LoggerFactory will return an ILogger after creating a Logger based on param passed from DB:

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时,必须以这种方式进行操作:

Now, when I need to use the Logger I have to do it in this way:

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

但是,我打算保留我的类而不进行任何实例化,我需要在MyService中使用Constructor DI,并且需要在Startup上注入所有依赖项:

But, I intend to keep my classes without any instantiation, I need to use Constructor DI in MyService and I need to inject all the dependencies on Startup:

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

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

But this will not work this we need to pass a concrete implementation. How to make that work using DI, is there a better approach for implementing that?

推荐答案

您的方法有两个错误:

  • Your services depend on the concrete LoggerFactory type which is a Dependency Inversion Principle violation.
  • Doing this extra initialization can make building the object graph unreliable, while injection constructors should be simple.
  • It hides the fact that the ILogger is the real service that your consumer depends upon. This makes the system harder to test, harder to maintain, and complicates object graph analysis.
  • The use of a factory is a smell, since factories are hardly ever the right solution.

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

Instead, your service should look as follows:

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

这大大简化了所有依赖ILogger的消费者.这也意味着,为MyService获取正确的ILogger成为组成根,这是掌握此知识的正确位置.

This dramatically simplifies all consumers that depend upon ILogger. This also means that getting the right ILogger for MyService becomes a responsibility of the Composition Root, which is the correct place to have this knowledge.

但是,这确实意味着您可能需要从ASP.NET Core的内置DI容器转移到功能更丰富的DI库,因为内置容器无法进行上下文感知的注册ILogger,同时使库也自动关联其他构造函数依赖项.

It does mean however that you might need to move away from the built-in DI container of ASP.NET Core to a more feature rich DI library, because the built-in container is not capable of making a context aware registration for ILogger while having the library auto-wire other constructor dependencies as well.

使用ASP.NET Core DI容器,您只能使用委托手动连接服务.例如:

With the ASP.NET Core DI container, you can only hand-wire your services using a delegate. For instance:

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

这篇关于在ASP.NET中使用依赖注入和工厂模式传递服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆