码迷,mamicode.com
首页 > Web开发 > 详细

ASP.NET Core中的依赖注入

时间:2020-02-28 12:08:45      阅读:66      评论:0      收藏:0      [点我收藏+]

标签:有一个   absolute   直接   ntop   injection   await   ecif   特定   private   

         ASP.NET Core支持DI软件设计模式,其是一种为了在类及其依赖对象之间实现控制反转(IoC)的一项技术。获取更多特定于MVC控制器的依赖注入的信息,可以参考Dependency injection into controllers in ASP.NET Core

依赖注入概述

        任何其他对象需要的一个对象都可以称之为依赖。检查如下具有一个WriteMessage方法的MyDependency类,app中的其他类会依赖它:

     

public class MyDependency
{
    public MyDependency()
    {
    }

    public Task WriteMessage(string message)
    {
        Console.WriteLine(
            $"MyDependency.WriteMessage called. Message: {message}");

        return Task.FromResult(0);
    }
}

         我们可以创建一个MyDependency类的实例来使得WriteMessage方法对于一个类是可用的。如下所示,MyDependency类便是IndexModel类的一个依赖:

   

public class IndexModel : PageModel
{
    MyDependency _dependency = new MyDependency();

    public async Task OnGetAsync()
    {
        await _dependency.WriteMessage(
            "IndexModel.OnGetAsync created this message.");
    }
}

        这个类创建并直接依赖于MyDependency类的实例。代码依赖(正如上述代码)是有问题的,基于如下理由,我们应该避免它:

  •                 如果要用一个不同的实现来替换MyDependency,使用了MyDependency的所有类必须要进行改动。
  •                 如果MyDependency类也具有依赖,那么MyDependency类的使用类必须对它们进行配置,会使得配置代码散布在整个app中。
  •                 这种实现难以进行单元测试,app应该使用一个模拟的或者微小的MyDependency类来进行单元测试,但在这种模式下这是不可能的。

       依赖注入通过以下方式解决这些问题:

  •               使用了接口或基类来对依赖的实现进行抽象。
  •               在一个服务容器中对依赖进行注册。ASP.NET Core提供了一个内置的服务容器,IServiceProvider。服务在Startup.ConfigureServices方法中进行注册。
  •               将服务注入到使用它们的类的构造函数中。框架负责创建一个依赖的实例,并在不再需要它的时候将其销毁。

       在示例代码中,IMyDependency接口定义了服务提供给app的方法:

      

public interface IMyDependency
{
    Task WriteMessage(string message);
}

        一个具体类型MyDependency实现了这个接口:

 

public class MyDependency : IMyDependency
{
    private readonly ILogger<MyDependency> _logger;

    public MyDependency(ILogger<MyDependency> logger)
    {
        _logger = logger;
    }

    public Task WriteMessage(string message)
    {
        _logger.LogInformation(
            "MyDependency.WriteMessage called. Message: {MESSAGE}", 
            message);

        return Task.FromResult(0);
    }
}

         MyDependency在其构造函数中 请求了一个ILogger<TCategoryName>。以链接的方式来使用依赖注入并不少见。每一个被请求的依赖都会依次请求它们自己的依赖。容器会对图形化的依赖进行解析并最终返回一个完整的解析后的服务。这一系列需要解析的服务被称为依赖树,或者依赖图,对象图。

        IMyDependency以及ILogger<TCategoryName>必须在服务容器中进行注册。IMyDependencyStartup.ConfigureServices中进行注册;而日志抽象架构负责ILogger<TCategoryName>的注册。所以它是一个框架提供的服务,其被框架默认注册。

        容器通过使用(generic) open types来对ILogger<TCategoryName>进行解析,而不需要对每一个泛型构造类型进行注册:

services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));

       在示例代码中,使用具体类型MyDependency来对IMyDependency服务进行注册。这个注册将服务的生命周期限定为一个请求的生命周期,服务的生命周期会在后续进行讨论:

  

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

    services.AddScoped<IMyDependency, MyDependency>();
    services.AddTransient<IOperationTransient, Operation>();
    services.AddScoped<IOperationScoped, Operation>();
    services.AddSingleton<IOperationSingleton, Operation>();
    services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));

    // OperationService depends on each of the other Operation types.
    services.AddTransient<OperationService, OperationService>();
}

注意,每一个services.Add{SERVICE_NAME}扩展方法都会添加(并潜在配置)了服务。比如services.AddMvc()添加了Razor视图和MVC支持。我们建议app遵从此约定,将扩展方法放置在此命名空间Microsoft.Extensions.DependencyInjection以对服务注册的分组进行封装。

        如果服务的构造函数需要一个内置类型,比如String,那么可以使用配置或者选项模式进行注入:

  

public class MyDependency : IMyDependency
{
    public MyDependency(IConfiguration config)
    {
        var myStringValue = config["MyStringKey"];

        // Use myStringValue
    }

    ...
}

          服务实例被使用它的类的构造函数所请求并被分配给一个私有字段。在整个类中,便可以使用这个字段来访问服务。

          在示例代码中,IMyDependency的实例会被请求并用来调用服务的WriteMessage方法。

public class IndexModel : PageModel
{
    private readonly IMyDependency _myDependency;

    public IndexModel(
        IMyDependency myDependency, 
        OperationService operationService,
        IOperationTransient transientOperation,
        IOperationScoped scopedOperation,
        IOperationSingleton singletonOperation,
        IOperationSingletonInstance singletonInstanceOperation)
    {
        _myDependency = myDependency;
        OperationService = operationService;
        TransientOperation = transientOperation;
        ScopedOperation = scopedOperation;
        SingletonOperation = singletonOperation;
        SingletonInstanceOperation = singletonInstanceOperation;
    }

    public OperationService OperationService { get; }
    public IOperationTransient TransientOperation { get; }
    public IOperationScoped ScopedOperation { get; }
    public IOperationSingleton SingletonOperation { get; }
    public IOperationSingletonInstance SingletonInstanceOperation { get; }

    public async Task OnGetAsync()
    {
        await _myDependency.WriteMessage(
            "IndexModel.OnGetAsync created this message.");
    }
}

 

ASP.NET Core中的依赖注入

标签:有一个   absolute   直接   ntop   injection   await   ecif   特定   private   

原文地址:https://www.cnblogs.com/qianxingmu/p/12376397.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!