基本使用
DI[1] 就不多说了,相信大家多多少少都有所了解。
我们直接上代码,首先新建一个控制台应用程序。
定义示例所使用的接口
public interface IAnimal
{
void Say();
}
实现此接口
public class Cat : IAnimal
{
public void Say()
{
Console.WriteLine("喵~");
}
}
public class Dog : IAnimal
{
public void Say()
{
Console.WriteLine("汪~");
}
}
NuGet Microsoft.Extensions.DependencyInjection
PM> Install-Package Microsoft.Extensions.DependencyInjection
这是在 .Net Core 中微软默认已经实现的DI[1:1]容器,并且使用广泛。
示例
IServiceCollection services = new ServiceCollection();
services.AddTransient<IAnimal, Dog>();
IServiceProvider provider = services.BuildServiceProvider();
var animal = provider.GetService<IAnimal>();
animal.Say();
Note
IServiceCollection
是一个重要的容器对象,用来确定注入关系。
IServiceProvider
也是一个重要的对象,用来获取实例。
生命周期
- Transient 瞬时 生命周期服务在它们每次请求时被创建。这一生命周期适合轻量级的无状态服务。
- Scoped 作用域 生命周期服务在每次请求时被创建一次。
- Singleton 单例 生命周期服务在它们第一次被请求时创建(或者你使用了直接创建的重载函数),并且每个后续请求将使用相同的实例,如果你的应用程序需要单例行为,则建议让服务容器管理服务的生命周期,而不是在自己的类中实现单例模式和管理对象的生命周期。
配置文件
在 .Net Core 中的配置文件一般为 appsettings.json 或者 appsettings.环境变量.json,现在我们可以将配置文件中某一个节点映射成一个模型类的实例。
配置节点
{
"Cryptography": {
"DesKey": "1dD%8Il4",
"TripleDesKey": "OTNbgW4#qVAl7wMqdbBN$Pjd",
"AesKey": "GaHleK8&qHXFG0p4vb3QB&xbUovs7&7n"
}
}
模型类
public sealed class CryptographyOptions
{
public string DesKey { get; set; }
public string TripleDesKey { get; set; }
public string AesKey { get; set; }
}
NuGet Microsoft.Extensions.Options
PM> Install-Package Microsoft.Extensions.Options
首先使用扩展函数注册所需的服务
services.AddOptions();
注册配置节点和模型类的注入关系
services.Configure<CryptographyOptions>(configuration.GetSection("Cryptography"));
Note
configuration
为 IConfiguration
的实例
示例
public sealed class Cryptography
{
public readonly CryptographyOptions Options;
public Cryptography(IOptions<CryptographyOptions> configOption)
{
Options = configOption.Value;
}
}
EntityFramework
NuGet Microsoft.EntityFrameworkCore
PM> Install-Package Microsoft.EntityFrameworkCore
可以通过 services.AddDbContext
或 services.AddDbContextPool
扩展函数来添加 EntityFramework 的 DbContext
对象的注入。
MVC
NuGet Microsoft.AspNetCore.Mvc
PM> Install-Package Microsoft.AspNetCore.Mvc
可以通过 services.AddMvc
扩展函数来添加MVC的对象注入关系。
使用 autofac 替换注入容器
在 Microsoft.Extensions.Options 所提供的注入容器中,目前我只发现了构造函数注入这种方式,但是接触过 DI[1:2] 的朋友都知道现在的注入容器多多少少都会提供一些更加高级的功能,比如 属性注入、条件注入、模块注入……等,所以我们在这里使用 autofac 来替换注入容器,实现这些高级功能。当然注入容器不止 autofac ,还有 Ninject、著名的 castleproject 中的 Windsor (Abp.Net 中就是使用的这个) 等等。
NuGet Autofac.Extensions.DependencyInjection
PM> Install-Package Autofac.Extensions.DependencyInjection
示例
在 .Net Core Mvc Application 中 Startup
类中的 ConfigureServices
函数,将 void
返回类型修改为 IServiceProvider
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
var builder = new ContainerBuilder();
//注入关系
builder.Populate(services);
return new AutofacServiceProvider(builder.Build());
}
Note
由于 MVC 中 Controller 的实例创建是由自己控制的,要实现高级注入功能,必须要让 Controller 的创建过程由注入容器来控制,所以修改代码为:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
services.AddMvc().AddControllersAsServices();
var builder = new ContainerBuilder();
//注入关系
builder.Populate(services);
return new AutofacServiceProvider(builder.Build());
}
参考资料
- ASP.NET Core中使用IOC三部曲(一.使用ASP.NET Core自带的IOC容器)
- ASP.NET Core中使用IOC三部曲(二.采用Autofac来替换IOC容器,并实现属性注入)
- ASP.NET Core中使用IOC三部曲(三.采用替换后的Autofac来实现AOP拦截)
- Welcome to Autofac’s documentation! — Autofac 4.0 documentation