依照约定的注册
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…
开源地址
MASA.BuildingBlocks:https://github.com/masastack/…
MASA.Contrib:https://github.com/masastack/…
MASA.Utils:https://github.com/masastack/…
MASA.EShop:https://github.com/masalabs/M…
MASA.Blazor:https://github.com/BlazorComp…
如果你对咱们的 MASA Framework 感兴趣,无论是代码奉献、应用、提 Issue,欢送分割咱们