本文是介绍netcore3.x版本的autofac的使用,以下是netcore2.X的
NetCore2.X面向接口编程中,Autofac(依赖注入)的基本使用
项目基本介绍
备注,项目源代码在上传GitHub后会展示链接
csdn代码链接
项目用的面向接口编程
(PS:面向接口编程的核心含义就是,层与层之间只通过接口关联)
- EptDemo是API主程序:依赖于IRepo和IServ
- EptDemo.IRepo是仓储接口层,负责提供Repo层的接口
- EptDemo.Repo是仓储层,负责与数据库进行数据串接,依赖Repo
- EptDemo.IServ是服务接口层,一般只提供给主程序,依赖于IRepo
- EptDemo.Serv是服务层,作用是完成与Repo层的数据串接,依赖于IRepo和IServe层
Autofac的实现依赖注入
加载Autofac包
管理nugut下载Autofac包并安装
包如下:
Autofac.Extensions.DependencyInjection
Autofac.Extras.DynamicProxy
注册
1.Startup类中,添加ConfigureContainer函数,进行注册。
AutofacModuleRegister是自己写的一个类,下面会介绍
//此函数名称是固定写法,不能变更
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterModule(new AutofacModuleRegister());
}
2.Program类中,更新CreateHostBuilder的配置,在执行创建HostBuilder后,注册Autofac服务
/// <summary>
/// 在createhostbuilder的地方使用Autofac
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
- 新建AutofacModuleRegister类,完成依赖注入操作
public class AutofacModuleRegister : Autofac.Module
{
// private static readonly ILog log = LogManager.GetLogger(typeof(AutofacModuleRegister));
protected override void Load(ContainerBuilder builder)
{
var basePath = AppContext.BaseDirectory;
#region 带有接口层的服务注入
var servicesDLLFile = Path.Combine(basePath, "EptDemo.Serv.dll");
var repositoryDllFile = Path.Combine(basePath, "EptDemo.Repo.dll");
if (!(File.Exists(servicesDLLFile) && File.Exists(repositoryDllFile)))
{
//1此处一开始可能是因为解耦的问题,导致运行的时候,dll文件没有编程
//1.1此时需要F6编译/工具栏build-build solution/解决方案右键编译
//2还有一个问题是,repo和serv层的数据再编译的时候,编译产生的文件不在EptDemo目录下
//2.1此时可以更改项目repo和serv的dll编译路径,项目右键-属性-编译-输出路径输入--“..\EptDemo\bin\Debug\”
var msg = "Repository.dll和services.dll丢失,因为项目解耦了,所以需要F6编译,再F5运行,请检查bin文件夹,并拷贝";
throw new Exception(msg);
}
//获取services.dll程序集服务,并注册
var assemblyServices = Assembly.LoadFrom(servicesDLLFile);
builder.RegisterAssemblyTypes(assemblyServices)
.AsImplementedInterfaces()
.InstancePerDependency()
.EnableInterfaceInterceptors();//引用Autofac.extras.DynamicProxy
//.InterceptedBy();//允许将拦截器服务的列表分配给注册 涉及到动态代理
//获取repository.dll程序集服务,并注册
var assemblyRepository = Assembly.LoadFrom(repositoryDllFile);
builder.RegisterAssemblyTypes(assemblyRepository)
.AsImplementedInterfaces()
.InstancePerDependency();
//.EnableInterfaceInterceptors()
//.InterceptedBy();
#endregion
}
}
重要:
1.因为本项目通过面向接口编程,所以EptDemo若是没有通过配置,是一定没有Ept.Serv和Ept.Repo两个dll文件的。
方案一:在Ept主项目中添加两个项目的引用,
方案二(推荐):将其他两个项目的dll编译路径变更到主项目中
右键Serv项目-属性-编译-输出路径-写入路径"…\EptDemo\bin\Debug",Ept是主项目的路径
其实目的就是,将对应项目编译后的dll放入到主程序下面。
Repo同上操作
2.因为整个解决方案是经过解耦的,所以基本上在更新代码后,最好编译一下整个解决方案。
使用
1.Serv的初始化:在各自的控制器中,初始化私有的IDemoServ变量,并在构造函数中赋值
private readonly IDemoServ _demoServ;
public WeatherForecastController(ILogger<WeatherForecastController> logger,IDemoServ demoServ)
{
_logger = logger;
_demoServ = demoServ;
}
2.Serv的使用
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
_demoServ.GetDemos();
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();
}