.net core 依赖注入, autofac 简单使用

简介:

.net core 依赖注入, autofac 简单使用
综述
ASP.NET Core  支持依赖注入, 也推荐使用依赖注入. 主要作用是用来降低代码之间的耦合度.

什么是控制反转?
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。

其中最常见的方式叫做"依赖注入"(Dependency Injection,简称DI),还有一种方式叫"依赖查找"(Dependency Lookup)

什么是依赖注入?
这个概念分开来理解

  1. 依赖, 当B类里要调用A类完成某个功能, 那么就可以说是B依赖于A.
public class ClassA
{
    public string FnA(string str)
    {
        return "A-" + str;
    }
}

public class ClassB
{
    ClassA ca = new ClassA();
    public string FnB(string str)
    {
        var art = ca.FnA(str);
        return "B-" + art;
    }
}

上面这种方式是很常见的, 但是并不符合依赖的原则. 依赖的原则是: 依赖于抽象,而不是具体的实现. 也就是B类不能直接依赖A类, 应该依赖A的抽象接口.

  1. 注入. 在这里C类不去实例化A类,而是通过其他人传递给我,我只用就好。简单来说就是别人对依赖创建实例化,我自己只负责使用,这个过程可以理解为注入.
public class ClassC
{
    ClassA _ca;
    public ClassC(ClassA ca)
    {
        _ca = ca;
    }
    public string FnC(string str)
    {
        var art = _ca.FnA(str);
        return "C-" + art;
    }
}

在上面的依赖中讲过, 最好不要直接依赖实现,应该依赖抽象接口. 通过注入我们了解到, 我们不应该直接实例化依赖项,而应该别人创建, 我们只负责使用. 综合一下, 我们就将原来的使用方式改为以下方式

/// <summary>
/// 抽象接口A
/// </summary>
public interface InterfaceA
{
    string FnA(string str);
}

/// <summary>
/// 抽象接口A的具体实现
/// </summary>
public class ClassA:InterfaceA
{
    public string FnA(string str)
    {
        return "A-" + str;
    }
}

/// <summary>
/// 传统方式
/// </summary>
public class ClassB
{
    ClassA ca = new ClassA();
    public string FnB(string str)
    {
        var art = ca.FnA(str);
        return "B-" + art;
    }
}
/// <summary>
/// 依赖注入方式, 1.依赖于抽象接口,而不是具体实现; 2.依赖项不由我们自己创建,而只是负责使用
/// </summary>
public class ClassD
{
    readonly InterfaceA _ica;
    public ClassD(InterfaceA ica)
    {
        _ica = ica;
    }
    public string FnD(string str)
    {
        var art = _ica.FnA(str);
        return "D-" + art;
    }
}

ClassB就是我们常见的使用方式, ClassD就是我们使用依赖注入的使用方式.

如何在.net core 里使用依赖注入?

  1. 创建抽象接口(过程略)
  2. 实现抽象接口(过程略)

3. 在Startup类的ConfigureServices方法中注册服务

   public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        services.AddTransient<InterfaceA, ClassA>();
    }
  1. 在Controller中使用, 通过在构造函数中获取实例, 然后使用
[ApiController]
[Route("[controller]/[action]")]
public class DemoController : ControllerBase
{
    private readonly InterfaceA _interfaceA;
    /// <summary>
    /// 通过构造函数获取实例
    /// </summary>
    /// <param name="interfaceA"></param>
    public DemoController(InterfaceA interfaceA)
    {
        _interfaceA = interfaceA;
    }
    public IActionResult TestGet()
    {
        var rt = _interfaceA.FnA("uuu");
        return Ok(rt);
    }
}

结果

以上就是一个简单的.net core 使用依赖注入的例子

如何选择服务的生命周期?
在上面的第三步, 在注册服务的时候我们使用的AddTransient , 除此之外还有 AddScoped,AddSingleton

AddTransient 暂时
暂时生存期服务 (AddTransient) 是每次从服务容器进行请求时创建的。 这种生存期适合轻量级、 无状态的服务。

AddScoped 范围内
作用域生存期服务 (AddScoped) 以每个客户端请求(连接)一次的方式创建。
注意:在中间件内使用有作用域的服务时,请将该服务注入至 Invoke 或 InvokeAsync 方法。 请不要通过构造函数注入进行注入,因为它会强制服务的行为与单一实例类似。 有关详细信息,请参阅 写入自定义 ASP.NET Core 中间件。

AddSingleton 单例
单一实例生存期服务 (AddSingleton) 是在第一次请求时(或者在运行 Startup.ConfigureServices 并且使用服务注册指定实例时)创建的。 每个后续请求都使用相同的实例。 如果应用需要单一实例行为,建议允许服务容器管理服务的生存期。 不要实现单一实例设计模式并提供用户代码来管理对象在类中的生存期。
注意:从单一实例解析有作用域的服务很危险。 当处理后续请求时,它可能会导致服务处于不正确的状态。

什么是容器?
讲到这里可能大家会有个疑问.

依赖注入把依赖的创建交给了别人, 我们只负责使用, 那么这个谁创建, 在哪儿创建, 怎么管理?

这个就引发了一个新的概念--容器. 容器就是负责关系的系统所有的依赖. 在我们.net core 有一个默认的容器, 专门用于管理这些依赖.

但是默认的容器在小型项目的时候够了,但是大型项目就不够了.

我们通过AddTransient这些方式去注册服务, 那么一个项目有非常的这种服务, 每一个都注册,在startup这个里面就变非常臃肿负责. 这个时候我们需要替换原来的容器.

如何更换默认容器?
在这里我们介绍一种常用的第三方容器: AutoFac, .net core 版本使用的是3.1 其他版本会略有不同.

一. nuget安装 Autofac.Extensions.DependencyInjection

 二. 修改 Program.cs 文件

添加一句

.UseServiceProviderFactory(new Autofac.Extensions.DependencyInjection.AutofacServiceProviderFactory())//Autofac

 三. 修改 Startup.cs

新增ConfigureContainer方法

    public void ConfigureContainer(ContainerBuilder builder)
    {
        // 方式一 默认注册
        builder.RegisterType<ClassA>().As<InterfaceA>();//注册 类似默认容器的services.AddTransient<InterfaceA, ClassA>();
    }

上面这种方式是默认的注册, 类似.net core 自带的注册. 但是并不合适我们批量注册, 下面介绍一种扫描程序集的注册方式

    public void ConfigureContainer(ContainerBuilder builder)
    {
        //方式二 扫描程序集, RegisterAssemblyTypes接收包含一个或多个程序集的数组作为参数. 默认地, 程序中所有具体的类都将被注册. 
        var asm = Assembly.Load("Service");//指定dll名称的程序集集
        var defulatAsm = Assembly.GetExecutingAssembly();//默认执行的dll
        builder.RegisterAssemblyTypes(asm, defulatAsm)
            .PublicOnly()//仅注册public的方法
            .Except<Service.DemoService>()//排除某个类
            .Where(t => t.Name.EndsWith("Service") || t.Name == "ClassA")//可以在这里写一些过滤类名规则
            .AsImplementedInterfaces();
    }

在controller里使用的方式和以前一样

参考文献

 .net core 依赖注入

Autofac 入门

原文地址https://www.cnblogs.com/fancyblogs/p/12564926.html

相关文章
|
7天前
|
数据可视化 网络协议 C#
C#/.NET/.NET Core优秀项目和框架2024年3月简报
公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等(打不开或者打开GitHub很慢的同学可以优先查看公众号推文,文末一定会附带项目和框架源码地址)。注意:排名不分先后,都是十分优秀的开源项目和框架,每周定期更新分享(欢迎关注公众号:追逐时光者,第一时间获取每周精选分享资讯🔔)。
|
3月前
|
开发框架 前端开发 JavaScript
盘点72个ASP.NET Core源码Net爱好者不容错过
盘点72个ASP.NET Core源码Net爱好者不容错过
63 0
|
3月前
|
开发框架 .NET
ASP.NET Core NET7 增加session的方法
ASP.NET Core NET7 增加session的方法
37 0
|
1月前
|
开发框架 人工智能 .NET
C#/.NET/.NET Core拾遗补漏合集(持续更新)
C#/.NET/.NET Core拾遗补漏合集(持续更新)
|
1月前
|
开发框架 中间件 .NET
C# .NET面试系列七:ASP.NET Core
## 第一部分:ASP.NET Core #### 1. 如何在 controller 中注入 service? 在.NET中,在ASP.NET Core应用程序中的Controller中注入服务通常使用<u>依赖注入(Dependency Injection)</u>来实现。以下是一些步骤,说明如何在Controller中注入服务: 1、创建服务 首先,确保你已经在应用程序中注册了服务。这通常在Startup.cs文件的ConfigureServices方法中完成。例如: ```c# services.AddScoped<IMyService, MyService>(); //
60 0
|
2月前
|
开发框架 前端开发 .NET
福利来袭,.NET Core开发5大案例,30w字PDF文档大放送!!!
为了便于大家查找,特将之前开发的.Net Core相关的五大案例整理成文,共计440页,32w字,免费提供给大家,文章底部有PDF下载链接。
32 1
福利来袭,.NET Core开发5大案例,30w字PDF文档大放送!!!
|
2月前
|
算法 BI API
C#/.NET/.NET Core优秀项目和框架2024年1月简报
C#/.NET/.NET Core优秀项目和框架2024年1月简报
|
3月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
38 0
|
26天前
|
开发框架 前端开发 .NET
进入ASP .net mvc的世界
进入ASP .net mvc的世界
25 0
|
26天前
mvc.net分页查询案例——mvc-paper.css
mvc.net分页查询案例——mvc-paper.css
4 0