Fireasy3 揭秘 -- 自动服务部署

目录

  • Fireasy3 揭秘 -- 依赖注入与服务发现
  • Fireasy3 揭秘 -- 自动服务部署
  • Fireasy3 揭秘 -- 使用 SourceGeneraor 改进服务发现
  • Fireasy3 揭秘 -- 使用 SourceGeneraor 实现动态代理(AOP)
  • Fireasy3 揭秘 -- 使用 Emit 构建程序集
  • Fireasy3 揭秘 -- 代码编译器及适配器
  • Fireasy3 揭秘 -- 使用缓存提高反射性能
  • Fireasy3 揭秘 -- 动态类型及扩展支持
  • Fireasy3 揭秘 -- 线程数据共享的实现
  • Fireasy3 揭秘 -- 配置管理及解析处理
  • Fireasy3 揭秘 -- 数据库适配器
  • Fireasy3 揭秘 -- 解决数据库之间的语法差异
  • Fireasy3 揭秘 -- 获取数据库的架构信息
  • Fireasy3 揭秘 -- 数据批量插入的实现
  • Fireasy3 揭秘 -- 使用包装器对数据读取进行兼容
  • Fireasy3 揭秘 -- 数据行映射器
  • Fireasy3 揭秘 -- 数据转换器的实现
  • Fireasy3 揭秘 -- 通用序列生成器和雪花生成器的实现
  • Fireasy3 揭秘 -- 命令拦截器的实现
  • Fireasy3 揭秘 -- 数据库主从同步的实现
  • Fireasy3 揭秘 -- 大数据分页的策略
  • Fireasy3 揭秘 -- 数据按需更新及生成实体代理类
  • Fireasy3 揭秘 -- 用对象池技术管理上下文
  • Fireasy3 揭秘 -- Lambda 表达式解析的原理
  • Fireasy3 揭秘 -- 扩展选择的实现
  • Fireasy3 揭秘 -- 按需加载与惰性加载的区别与实现
  • Fireasy3 揭秘 -- 自定义函数的解析与绑定
  • Fireasy3 揭秘 -- 与 MongoDB 进行适配
  • Fireasy3 揭秘 -- 模块化的实现原理

  前篇已经介绍了依赖注入与服务发现,还有另外一种机制是服务部署,顾名思义就是可以在程序集中定义一个实现,再手动添加依赖注入,这一般是有选择性的注入。
  回顾 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://github.com/faib920/fireasy3 ,欢迎大家前来捧场。

  本文相关代码请参考:
  https://github.com/faib920/fireasy3/src/libraries/Fireasy.Common/DependencyInjection

  更多内容请移步官网 http://www.fireasy.cn 。

posted @ 2023-03-02 23:11  fireasy  阅读(149)  评论(1编辑  收藏  举报