乐趣区

关于后端:7依赖注入

依照约定的注册

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
  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
  2. 新建类StorageOptions

    public class StorageOptions : ITransientDependency
    {}
  3. 新建类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,欢送分割咱们

退出移动版