IOC模式和依賴注入是近年來非常流行的一種模式,相信大家都不陌生了,在Asp.Net Core中提供了依賴注入作為內置的基礎設施,如果仍不熟悉依賴注入的讀者,可以看看由我們翻譯的Asp.Net Core中文文檔中依賴注入的相關章節: ASP.NET Core 中文文檔 第三章 原理(10)依賴注入。基於IoC的重要性,AspectCore在提供Aop特性的同時,同樣提供了可以和Aop無縫集成使用的輕量級、高性能IoC容器AspectCore.Injector
。
開始使用
AspectCore.Injector
內置在AspectCore.Core包中,我們可以通過nuget獲取
Install-Package AspectCore.Core -pre
容器和服務注冊
在AspectCore.Injector中容器命名為IServiceContainer
,使用容器的默認實現來創建一個容器,並且提供了類型,實例,和工廠三種方式來注冊服務:
IServiceContainer services = new ServiceContainer();
//使用類型注冊服務
services.AddType<ILogger, Logger>();
//使用實例注冊服務,服務的生命周期限定為單例
services.AddInstance<ITaskService>(new TaskService());
//使用委托工廠注冊服務
services.AddDelegate<ITaskService, TaskService>(resolver => new TaskService());
服務解析
AspectCore.Injector通過IServiceResolver來解析服務:
//創建服務解析器
IServiceResolver serviceResolver = services.Build();
//解析單個服務
ISampleService sampleService = serviceResolver.Resolve<ISampleService>();
//解析單個服務,並且驗證是否為null,為null則拋出異常
ISampleService sampleServiceRequired = serviceResolver.ResolveRequired<ISampleService>();
//解析服務集合,如果未注冊,則為空集合
IEnumerable<ISampleService> sampleServices = serviceResolver.ResolveMany<ISampleService>();
依賴注入
AspectCore.Injector提供構造器注入和屬性兩種方式:
public interface ISampleService
{
}
public class SampleService : ISampleService
{
private readonly ISampleRepository _sampleRepository;
private readonly ILogger _logger;
//構造器注入
public SampleService(ISampleRepository sampleRepository, ILogger logger)
{
_sampleRepository = sampleRepository;
_logger = logger;
}
}
public interface ISampleRepository
{
}
public class SampleRepository : ISampleRepository
{
//屬性注入。屬性注入的條件為標記FromContainer特性,並且允許set。滿足條件的屬性自動注入
[FromContainer]
public ILogger Logger { get; set; }
}
生命周期
AspectCore.Injector提供以下生命周期:
瞬時
瞬時(Transient)生命周期服務在它們每次請求時被創建。這一生命周期適合輕量級的,無狀態的服務。
作用域
作用域(Scoped)生命周期服務在每個作用域內被創建一次。
單例
單例(Singleton)生命周期服務在它們第一次被解析時創建,並且每個后續解析將使用相同的實例。如果你的應用程序需要單例行為,建議讓服務容器管理服務的生命周期而不是在自己的類中實現單例模式和管理對象的生命周期。
Aop集成
在AspectCore.Injector中默認開啟在AspectCore.DynamicProxy的Aop集成,並可通過IServiceContainer的Configure方法進行Aop的配置。
services.Configure(config =>
{
config.Interceptors.AddTyped<SampleInterceptor>();
});
在Asp.Net Core中使用AspectCore.Injector
安裝AspectCore.Extensions.DependencyInjection nuget包
Install-Package AspectCore.Extensions.DependencyInjection -pre
在修改ConfigureServices:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
//添加你的服務...
//將IServiceCollection的服務添加到ServiceContainer容器中
var container = services.ToServiceContainer();
return container.Build();
}
只需要兩行代碼即可在Asp.Net Core中使用AspectCore.Injector替換默認的DependencyInjection。
性能
Autofac是目前.net/.net core較為流行的IoC容器之一,我們把Autofac(4.6.2版本)作為性能對比目標。分別從解析簡單對象,屬性注入和構造器注入三個方面對比性能。
Benckmark類編寫如下:
[AllStatisticsColumn]
[MemoryDiagnoser]
public class Benckmarks
{
private readonly IServiceResolver serviceResolver;
private readonly IContainer container;
public Benckmarks()
{
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Logger>().As<ILogger>().InstancePerDependency();
containerBuilder.RegisterType<TaskService>().As<ITaskService>().InstancePerDependency();
containerBuilder.RegisterType<SampleRepository>().As<ISampleRepository>().InstancePerDependen
containerBuilder.RegisterType<SampleService2>().As<ISampleService>().InstancePerDependency();
container = containerBuilder.Build();
var serviceContainer = new ServiceContainer();
serviceContainer.AddType<ILogger, Logger>(Lifetime.Transient);
serviceContainer.AddType<ITaskService, TaskService>(Lifetime.Transient);
serviceContainer.AddType<ISampleRepository, SampleRepository>(Lifetime.Transient);
serviceContainer.AddType<ISampleService, SampleService2>(Lifetime.Transient);
serviceResolver = serviceContainer.Build();
}
[Benchmark]
public object Autofac_Sample_Resolve()
{
return container.Resolve<ITaskService>();
}
[Benchmark]
public object AspectCore_Sample_Resolve()
{
return serviceResolver.Resolve<ITaskService>();
}
[Benchmark]
public object Autofac_PropertyInjection()
{
return container.Resolve<ISampleRepository>();
}
[Benchmark]
public object AspectCore_PropertyInjection()
{
return serviceResolver.Resolve<ISampleRepository>();
}
[Benchmark]
public object Autofac_ConstructorInjection()
{
return container.Resolve<ISampleService>();
}
[Benchmark]
public object AspectCore_ConstructorInjection()
{
return serviceResolver.Resolve<ISampleService>();
}
}
使用Release模式運行Benchmark:
BenchmarkDotNet=v0.10.8, OS=Windows 10 Threshold 2 (10.0.10586)
Processor=Intel Core i5-4590 CPU 3.30GHz (Haswell), ProcessorCount=4
Frequency=3215206 Hz, Resolution=311.0221 ns, Timer=TSC
dotnet cli version=2.0.0
[Host] : .NET Core 4.6.00001.0, 64bit RyuJIT
DefaultJob : .NET Core 4.6.00001.0, 64bit RyuJIT
| Method | Mean | Min | Max | Op/s | Gen 0 | Allocated |
|-------------------------------- |------------:|------------:|------------:|-------------:|-------:|----------:|
| Autofac_Sample_Resolve | 494.83 ns | 482.52 ns | 506.58 ns | 2,020,908.9 | 0.2384 | 752 B |
| AspectCore_Sample_Resolve | 88.52 ns | 87.92 ns | 89.31 ns | 11,296,837.3 | 0.0279 | 88 B |
| Autofac_PropertyInjection | 2,014.46 ns | 2,004.18 ns | 2,028.83 ns | 496,411.0 | 0.5875 | 1856 B |
| AspectCore_PropertyInjection | 307.55 ns | 303.61 ns | 310.74 ns | 3,251,544.6 | 0.1063 | 336 B |
| Autofac_ConstructorInjection | 1,465.71 ns | 1,454.43 ns | 1,480.38 ns | 682,263.5 | 0.6084 | 1920 B |
| AspectCore_ConstructorInjection | 284.94 ns | 283.55 ns | 286.05 ns | 3,509,500.8 | 0.0987 | 312 B |
有問題反饋
Sample:IoC-Sample
如果您有任何問題,請提交 Issue 給我們。
Github : https://github.com/dotnetcore/AspectCore-Framework
AspectCore Group QQ群: 306531723