依赖注入
Masa的依赖注入系统是基于Microsoft的依赖注入扩展库(Microsoft.Extensions.DependencyInjection nuget包)开发的,因此,它的文档在Masa中也是有效的。
按照约定的注册
Masa引入了按照约定进行服务注册,依据约定大于配置,开发者无需做任何事,框架会自动完成注册
依赖接口
-
ISingletonDependency: 注册生命周期为Singleton的服务
-
IScopedDependency: 注册生命周期为Scoped的服务
-
ITransientDependency: 注册生命周期为Transient的服务
-
IAutoFireDependency: 自动触发(与ISingletonDependency、IScopedDependency、ITransientDependency结合使用,在服务自动注册结束后触发一次获取服务操作,仅继承IAutoFireDependency不起作用)
public class StorageOptions : ITransientDependency { }
特性
IgnoreInjection
忽略注入,用于排除不被自动注入
-
Cascade: 设置为true时,当前类以及子类都不再被自动注册,设置为false,仅当前类不被自动注册(默认false)
public class BaseService : ISingletonDependency { public static int Count { get; set; } = 0; public BaseService() { Count++; } public BaseService(bool isChildren) { } } [IgnoreInjection] public class GoodsBaseService : BaseService { public GoodsBaseService() : base(true) { } } public class GoodsService : GoodsBaseService { public static int GoodsCount { get; set; } = 0; public GoodsService() { GoodsCount++; } }
效果等同于:services.AddSingleton<
BaseService
>(); services.AddSingleton<GoodsService
>();
Dependency
配合ISingletonDependency、IScopedDependency、ITransientDependency使用,实现服务仅被注册一次
-
TryRegister: 设置true则仅当服务未注册时才会被注册,类似IServiceCollection的TryAdd ... 扩展方法.
public interface ICache : ISingletonDependency { void Set(string key, string value); } [Dependency(TryRegister = true)] public class EmptyCache : ICache { public void Set(string key, string value) { throw new NotSupportedException($"暂不支持{nameof(Set)}方法"); } } public class MemoryCache : ICache { private readonly ConcurrentDictionary<string, Lazy<string>> _dicCache = new(); public void Set(string key, string value) { _ = _dicCache.AddOrUpdate ( key, k => new Lazy<string>(() => value, LazyThreadSafetyMode.ExecutionAndPublication), (_, _) => new Lazy<string>(() => value, LazyThreadSafetyMode.ExecutionAndPublication) ).Value; } }
效果等同于:services.AddSingleton<
ICache
,MemoryCache
>();
-
ReplaceServices: 设置true则替换之前已经注册过的服务,类似IServiceCollection的Replace ... 扩展方法.
public interface IEncryptionService : ISingletonDependency { string MethodName { get; } } [Dependency(ReplaceServices = true)] public class Sha1EncryptionService : IEncryptionService { public string MethodName => "Sha1"; } public class Md5EncryptionService : IEncryptionService { public string MethodName => "Md5"; }
效果等同于:services.AddSingleton<
IEncryptionService
,Sha1EncryptionService
>();
快速入门
- 安装.Net 6.0
-
新建单元测试项目
Assignment.DependencyInjection
,选择MSTest
,并安装Masa.Utils.Extensions.DependencyInjection
dotnet new xunit -o Assignment.DependencyInjection cd Assignment.DependencyInjection dotnet add package Masa.Utils.Extensions.DependencyInjection --version 0.5.0-preview.2
-
新建类
StorageOptions
public class StorageOptions : ITransientDependency { }
-
新建类
DITest
[TestClass] public class DITest { private IServiceCollection _services; [TestInitialize] public void Init() { _services = new ServiceCollection(); _services.AddAutoInject();//执行自动注入 } [TestMethod] public void TestAutoInject() { Assert.IsTrue(_services.Any<StorageOptions>(ServiceLifetime.Transient));//判断StorageOptions注册成功,且生命周期为Transient } private IServiceProvider ServiceProvider => _services.BuildServiceProvider(); }
总结
如果需要使用按照约定自动注册服务,则请记住
- 根据业务需要,则指定类或接口中实现以下接口
ISingletonDependency
单例(项目启动后仅初始化一次)IScopedDependency
请求 (每次请求仅初始化一次)ITransientDependency
瞬时(每次获取都会被初始化)
- 抽象类不会被自动注册
- 如果你有一个自定义接口
IRepository
,且希望接口以及对应的默认实现类RepositoryBase
会被自动注册生命周期为Scoped,则接口IRepository
应该继承IScopedDependency
- 如果你希望默认提供的
RepositoryBase
可以被用户定义的类替换,则应该在RepositoryBase
上方增加[Dependency(TryRegister = true)],那用户仅需要实现IRepository
即可 - 或不更改默认提供的
RepositoryBase
,用户实现IRepository
后,并在新的实现类上方增加[Dependency(ReplaceServices = true)]
- 如果你希望默认提供的
本章源码
Assignment07
https://github.com/zhenlei520/MasaFramework.Practice
开源地址
MASA.Framework:https://github.com/masastack/MASA.Framework
MASA.EShop:https://github.com/masalabs/MASA.EShop
MASA.Blazor:https://github.com/BlazorComponent/MASA.Blazor
如果你对我们的 MASA Framework 感兴趣,无论是代码贡献、使用、提 Issue,欢迎联系我们
本文来自博客园,作者:磊_磊,转载请注明原文链接:https://www.cnblogs.com/zhenlei520/p/16497621.html
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利