1.控制反转
(1)定义
控制:控制对象的创建、实例化;控制对象之间的依赖关系
反转:由于应用程序不是主动创建对象,而是被动地等待对象容器注入所需要的资源,因此称之为反转
(2)好处
松耦合
2.依赖注入
实现控制反转的一种方式
3.区别与联系
控制反转(Inversion of Control,缩写为IoC):
使用对象容器反过来控制应用程序所需要的外部资源的一种程序开发思想。
面向对象编程中的一种设计原则,是一种设计思想。
依赖注入(Dependency Injection,简称DI):
实现控制反转最常用的方式。
依赖注入是一种具体的实施方法,容器创建好实例后再注入调用者称为依赖注入。
4.Autofac使用例子
说明
该例子可实现自动加载程序集,在控制器中自动通过属性注册类、实现接口,达到依赖注入的效果
建立工程
环境
.Net 5
新建.Net 5工程,切换启动项
nuget依赖包
Autofac 6.4.6
Autofac.Extensions.DependencyInjection 8.0.0
Program.cs:引入Autofac创建服务工厂组件
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
namespace AutoContainerCore.Api
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())//引入Autofac创建服务工厂组件
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
Startup.cs:添加一个ConfigureContainer方法
这个方法的作用加载名称为(工程名+.IBusiness)/(工程名+.Business)的程序集,并注册实现里面的接口;
所以接下来必须要再创建这样名称的两个工程
public void ConfigureContainer(ContainerBuilder builder)
{
var serviceName = AppDomain.CurrentDomain.FriendlyName.Replace(".Api", "").Replace(".API", "");
Assembly[] assArr = new Assembly[]
{
Assembly.Load(new AssemblyName(serviceName+".IBusiness")),
Assembly.Load(new AssemblyName(serviceName+".Business"))
};
foreach (var ass in assArr)
{
//找到Business结尾且为非抽象类
var serviceTypes = ass.GetTypes()
.Where(t => !t.GetTypeInfo().IsAbstract);
foreach (var serviceType in serviceTypes)
{
foreach (var interType in serviceType.GetInterfaces())
{
var sname = serviceType.Name;
var Iname = interType.Name;
builder.RegisterType(serviceType).As(interType)
.InstancePerDependency()//默认模式,每次调用,都会重新实例化对象;每次请求都创建一个新的对象;
.AsImplementedInterfaces()//自动以其实现的所有接口类型暴露(包括IDisposable接口);可以把一个类注册给它实现的全部接口
.InstancePerLifetimeScope()//同一个Lifetime生成的对象是同一个实例
.PropertiesAutowired();//支持属性注入的方法;
}
}
//控制器实例的注入
var sss = typeof(Startup).GetTypeInfo().Assembly.DefinedTypes;
var controllerTypes = typeof(Startup).GetTypeInfo().Assembly.DefinedTypes.
Where(x => x.IsClass && typeof(ControllerBase).GetTypeInfo()
.IsAssignableFrom(x))// 返回一个值,该值指示是否可以将指定类型分配给当前类型
.Select(x => x.AsType())
.ToArray();
builder.RegisterTypes(controllerTypes);
}
}
创建AutoContainerCore.IBusiness类库项目
编写一个接口
using System.Threading.Tasks;
namespace AutoContainerCore.IBusiness
{
public interface IUserBusiness
{
Task<string> Debug();
}
}
创建AutoContainerCore.Business类库项目
引入IBusiness接口
AutoContainerCore.Business项目新建业务类UserBusiness,并实现接口
using AutoContainerCore.IBusiness;
using System;
using System.Threading.Tasks;
namespace AutoContainerCore.Business
{
public class UserBusiness : IUserBusiness
{
public async Task<string> Debug()
{
await Task.CompletedTask;
return "test";
}
}
}
在AutoContainerCore.Api项目中引入
注意:必须两个项目都引入,否则会报错
AutoContainerCore.IBusiness
AutoContainerCore.Business
在AutoContainerCore.Api项目的controller中依赖注入,调用接口的方法
using AutoContainerCore.IBusiness;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace AutoContainerCore.Api.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
/// <summary>
/// 属性依赖
/// </summary>
public IUserBusiness _iUserBusiness { get; }
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
/// <summary>
/// 构造函数中的依赖注入
/// </summary>
/// <param name="logger"></param>
/// <param name="userBusiness"></param>
public WeatherForecastController(ILogger<WeatherForecastController> logger, IUserBusiness userBusiness)
{
_logger = logger;
_iUserBusiness = userBusiness;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
/// <summary>
/// 调用接口方法
/// </summary>
/// <returns></returns>
[HttpPost("Debug")]
public async Task<string> Debug()
{
var result = await _iUserBusiness.Debug();
return result;
}
}
}
运行
swagger调用debug
看到返回值为test