目录
- Fireasy3 揭秘 -- 依赖注入与服务发现
- Fireasy3 揭秘 -- 自动服务部署
- Fireasy3 揭秘 -- 使用 SourceGeneraor 改进服务发现
- Fireasy3 揭秘 -- 使用 SourceGeneraor 实现动态代理(AOP)
前篇已经介绍了依赖注入与服务发现,还有另外一种机制是服务部署,顾名思义就是可以在程序集中定义一个实现,在手动添加依赖注入,这一般是有选择性的注入。
回顾 DefaultServiceDiscoverer
类,你会发现有这么一个 ConfigureServices
方法,前篇是没有介绍过的,专门提到本篇里来细说。如下:
/// <summary>
/// 发现工作目录中所有程序集中的依赖类型。
/// </summary>
/// <param name="services"></param>
private void DiscoverServices(IServiceCollection services)
{
foreach (var assembly in GetAssemblies())
{
if (_options?.AssemblyFilters?.Any(s => s.IsFilter(assembly)) == true)
{
continue;
}
if (_options?.AssemblyFilterPredicates?.Any(s => s(assembly)) == true)
{
continue;
}
_assemblies.Add(assembly);
ConfigureServices(services, assembly);
DiscoverServices(services, assembly);
}
}
在 ConfigureServices
方法里,通过 ServicesDeployAttribute
特性去查找程序集中定义的部署类。所谓部署类,实际上是往 services 里添加服务描述(服务与实现的关系映射)。如下:
private void ConfigureServices(IServiceCollection services, Assembly assembly)
{
var attrs = assembly.GetCustomAttributes<ServicesDeployAttribute>();
if (attrs.Any())
{
foreach (var attr in attrs.OrderBy(s => s.Priority))
{
if (Activator.CreateInstance(attr.Type) is IServicesDeployer deployer)
{
deployer.Configure(services);
}
}
}
else
{
var types = assembly.GetTypes().Where(t => t.IsClass && !t.IsAbstract && typeof(IServicesDeployer).IsAssignableFrom(t)).ToList();
var deployers = types
.Select(s => Activator.CreateInstance(s))
.Where(s => s is IServicesDeployer)
.Cast<IServicesDeployer>()
.ToList();
deployers.ForEach(s => s!.Configure(services));
}
}
它首先会通过 ServicesDeployAttribute
特性去找所指定的部署类,这样的好处在于直达终点,省去了遍列程序集中的所有类,逐个去判断有没有实现了 IServicesDeployer
接口。找到这些部署类后,实例化一个对象,调用 Configure
去配置容器。
采用这种部署器后,你只需要在你的程序集里定义一个实现 IServicesDeployer
接口的类,想怎么 Add 就怎么 Add,灵活性要高。比如在 Fireasy.Data 项目中,就可以定义如下:
[assembly: ServicesDeploy(typeof(DataServicesDeployer))]
namespace Fireasy.Data.DependencyInjection
{
/// <summary>
/// 服务部署。
/// </summary>
public class DataServicesDeployer : IServicesDeployer
{
void IServicesDeployer.Configure(IServiceCollection services)
{
services.AddSingleton<IProviderManager, DefaultProviderManager>();
services.AddSingleton<IDatabaseFactory, DefaultDatabaseFactory>();
services.AddSingleton<IRowMapperFactory, DefaultRowMapperFactory>();
services.AddScoped<IDatabase>(sp => sp.GetRequiredService<IDatabaseFactory>().CreateDatabase());
services.AddScoped<DistributedController>();
}
}
}
你可以不用关注它在什么时候被部署,因为只要在起先调用了 AddFireasy 方法后,它就被不知不觉调用了。
同一个程序集里可以存在多个部署类,ServicesDeployAttribute
也是允许多次指定的,甚至可以使用 Priority 来指定被部署的优先级。
最后,奉上 Fireasy 3
的开源地址:https://gitee.com/faib920/fireasy3 ,欢迎大家前来捧场。
本文相关代码请参考 https://gitee.com/faib920/fireasy3/src/libraries/Fireasy.Common/DependencyInjection 下的相关文件。
更多内容请移步官网 http://www.fireasy.cn 。
标签:assembly,--,部署,services,IServicesDeployer,Fireasy3,揭秘 From: https://www.cnblogs.com/fireasy/p/17173997.html