写点什么

7. 依赖注入

  • 2022 年 7 月 25 日
  • 本文字数:2585 字

    阅读完需:约 8 分钟

按照约定的注册

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>();

快速入门


  1. 新建单元测试项目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
复制代码


  1. 新建类StorageOptions


    public class StorageOptions : ITransientDependency    {          }
复制代码


  1. 新建类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.BuildingBlocks:https://github.com/masastack/MASA.BuildingBlocks


MASA.Contrib:https://github.com/masastack/MASA.Contrib


MASA.Utils:https://github.com/masastack/MASA.Utils


MASA.EShop:https://github.com/masalabs/MASA.EShop


MASA.Blazor:https://github.com/BlazorComponent/MASA.Blazor


如果你对我们的 MASA Framework 感兴趣,无论是代码贡献、使用、提 Issue,欢迎联系我们



发布于: 13 小时前阅读数: 22
用户头像

还未添加个人签名 2021.10.26 加入

还未添加个人简介

评论

发布
暂无评论
7.依赖注入_后端_MASA技术团队_InfoQ写作社区