Fireasy3 揭秘 -- 自动服务部署

  金牌会员 | 2023-3-3 04:24:21 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 868|帖子 868|积分 2604

目录

  前篇已经介绍了依赖注入与服务发现,还有另外一种机制是服务部署,顾名思义就是可以在程序集中定义一个实现,在手动添加依赖注入,这一般是有选择性的注入。
  回顾 DefaultServiceDiscoverer 类,你会发现有这么一个 ConfigureServices 方法,前篇是没有介绍过的,专门提到本篇里来细说。如下:
  1.     /// <summary>
  2.     /// 发现工作目录中所有程序集中的依赖类型。
  3.     /// </summary>
  4.     /// <param name="services"></param>
  5.     private void DiscoverServices(IServiceCollection services)
  6.     {
  7.         foreach (var assembly in GetAssemblies())
  8.         {
  9.             if (_options?.AssemblyFilters?.Any(s => s.IsFilter(assembly)) == true)
  10.             {
  11.                 continue;
  12.             }
  13.             if (_options?.AssemblyFilterPredicates?.Any(s => s(assembly)) == true)
  14.             {
  15.                 continue;
  16.             }
  17.             _assemblies.Add(assembly);
  18.             ConfigureServices(services, assembly);
  19.             DiscoverServices(services, assembly);
  20.         }
  21.     }
复制代码
  在 ConfigureServices 方法里,通过 ServicesDeployAttribute 特性去查找程序集中定义的部署类。所谓部署类,实际上是往 services 里添加服务描述(服务与实现的关系映射)。如下:
  1.     private void ConfigureServices(IServiceCollection services, Assembly assembly)
  2.     {
  3.         var attrs = assembly.GetCustomAttributes<ServicesDeployAttribute>();
  4.         if (attrs.Any())
  5.         {
  6.             foreach (var attr in attrs.OrderBy(s => s.Priority))
  7.             {
  8.                 if (Activator.CreateInstance(attr.Type) is IServicesDeployer deployer)
  9.                 {
  10.                     deployer.Configure(services);
  11.                 }
  12.             }
  13.         }
  14.         else
  15.         {
  16.             var types = assembly.GetTypes().Where(t => t.IsClass && !t.IsAbstract && typeof(IServicesDeployer).IsAssignableFrom(t)).ToList();
  17.             var deployers = types
  18.                 .Select(s => Activator.CreateInstance(s))
  19.                 .Where(s => s is IServicesDeployer)
  20.                 .Cast<IServicesDeployer>()
  21.                 .ToList();
  22.             deployers.ForEach(s => s!.Configure(services));
  23.         }
  24.     }
复制代码
  它首先会通过 ServicesDeployAttribute 特性去找所指定的部署类,这样的好处在于直达终点,省去了遍列程序集中的所有类,逐个去判断有没有实现了 IServicesDeployer 接口。找到这些部署类后,实例化一个对象,调用 Configure 去配置容器。
  采用这种部署器后,你只需要在你的程序集里定义一个实现 IServicesDeployer 接口的类,想怎么 Add 就怎么 Add,灵活性要高。比如在 Fireasy.Data 项目中,就可以定义如下:
  1. [assembly: ServicesDeploy(typeof(DataServicesDeployer))]
  2. namespace Fireasy.Data.DependencyInjection
  3. {
  4.     /// <summary>
  5.     /// 服务部署。
  6.     /// </summary>
  7.     public class DataServicesDeployer : IServicesDeployer
  8.     {
  9.         void IServicesDeployer.Configure(IServiceCollection services)
  10.         {
  11.             services.AddSingleton<IProviderManager, DefaultProviderManager>();
  12.             services.AddSingleton<IDatabaseFactory, DefaultDatabaseFactory>();
  13.             services.AddSingleton<IRowMapperFactory, DefaultRowMapperFactory>();
  14.             services.AddScoped<IDatabase>(sp => sp.GetRequiredService<IDatabaseFactory>().CreateDatabase());
  15.             services.AddScoped<DistributedController>();
  16.         }
  17.     }
  18. }
复制代码
  你可以不用关注它在什么时候被部署,因为只要在起先调用了 AddFireasy 方法后,它就被不知不觉调用了。
  同一个程序集里可以存在多个部署类,ServicesDeployAttribute 也是允许多次指定的,甚至可以使用 Priority 来指定被部署的优先级。

  最后,奉上 Fireasy 3 的开源地址:https://gitee.com/faib920/fireasy3 ,欢迎大家前来捧场。
  本文相关代码请参考:
  https://gitee.com/faib920/fireasy3/src/libraries/Fireasy.Common/DependencyInjection
  更多内容请移步官网 http://www.fireasy.cn 。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表