zoukankan      html  css  js  c++  java
  • Reface.AppStarter 框架初探

    Reface.AppStarter 是一种基于 .NetFramework 的应用程序启动模式,使用该启动模式,你可以轻松的得到以下功能 : 

    • IOC / DI 自动注册与装配
    • 简化配置
    • 垂直模块化你的代码
    • 事件总线功能
    • 命令总线 功能
    • 定义模块的依赖项
    • 对模块内的类型进行扫描并分类管理

    1 安装

    通过 Nuget 你可以很轻松的安装并使用它。

    2 设计理念

    2.1 模块化

    模块是系统组成的最小颗粒,

    每一个模块都应当向系统提供一个单一的功能或业务,比如 Excel导出,缓存,用户管理等等。

    原则上,我们建议你的每一个 Library 都是一个模块。

    在 Reface.AppStarter 中,每一个模块都应当申明一个 AppModule 作为提供给外部依赖的类型。

    public class MyAppModule : AppModule
    {
    }

    2.2 模块依赖

    模块与模块之间存在依赖关系,

    如上图,启动模块依赖模块A,启动模块就可以得到模块A中的功能,模块A也可以增加启动模块的功能。

    整个系统只能有一个启动模块,由它作为 ROOT 向下展开。

    例如

    一个用户模块可能依赖 Excel导入导出、日志、缓存模块,一个缓存模块可能依赖 AOP、日志模块等等。

    在 Reface.AppStarter 中,当 A 模块依赖 B 模块时,我们把 B 称作为的 DependentModule,将 A 称作 B 的 TargetModule,

    我们可以利用 Attribute 轻松的实现模块依赖的定义,下面的例子就是一个依赖了 用户、订单 的模块。

    [UserAppModule]
    [OrderAppModule]
    public class MyAppModule
    {
    }

    2.3 类型扫描与分类

    当我们使用模块以树状的形式构建了系统后,

    Reface.AppStarter 就可以对这个树状图中的模块进行自顶向下的扫描,

    扫描每一个模块中的类型,并将一切标有 ScannableAttribute(或继承) 特征的类型收集,允许被依赖的模块访问这些被收集的类型,并对这些类型进行增强的操作。

    [Scannable]
    public class MyClass
    {
    }

    形如上面的类型,就可以被依赖的 AppModule 获取,并对其做出额外的增强,比如 IOC / DI ,AOP的代理类生成等等。

    Reface.AppStarter 所提供的 IOC / DI 的自动注册和自动装置就是基于此功能实现的。

    2.4 应用程序构建

    Reface.AppStarter 分为配置与启动两个阶段。

    配置阶段你需要声明一个 AppSetup ,并让它启动你的取顶层模块即可。

    AppSetup setup = new AppSetup();
    App app = setup.Start(new MyAppModule());

    App 实例承载了 Reface.AppStarter 中的所有容器,有关容器会在以后的文章中做详解。

    最简单的用法,是从 app 中得到 IComponentContainer 并用它创建 IOC / DI 组件。

    var container = app.GetAppContainer<IComponentContainer>();
    ITestService service = container.CreateComponent<ITestService>();
    service.Do();

    3 使用方法

    3.1 为你的所有 Library 创建 AppModule

    • 你可以通过 AppModule 实现以下功能
    • 创建一个可以由外部依赖的 AppModule
    • 定义自己所依赖的其它 AppModule
    • 增强依赖自己的 TargetModule 的功能
    • 注册额外的组件至 IOC / DI 容器
    • 替换  IOC / DI 容器中已注册的组件

    下面的示例中展示了上述所的大部分常用功能

        [AutoConfigAppModule]
        [ComponentScanAppModule]
        [UserAppModule]
        public class TestAppModule : AppModule
        {
            [ComponentCreator]
            public IUserService GetUserService(ILangProvider provider)
            {
                return new DefaultUserService(provider);
            }
    
            [ReplaceCreator]
            public ITestService GetTestService()
            {
                return new SecondTestService();
            }
        }

    代码解释

    • 所有  AppModule 都要实现 IAppModule 的接口,IAppModule 的一个简便的实现就是 AppModule,它允许开发者直接通过 Attribute 来定义依赖项
    • 通过 Attribute,TestAppModule 依赖了三个其它模块
      • AppConfigAppModule,是一个自动配置模块,这是 Reface.AppStarter 自带的
      • ComponentScanAppModule,是一个 IOC / DI 组件扫描的模块,这也是 Reface.AppStarter 自带的
      • UserAppModule,这是一个关于用户的业务模块,这是一个示例模块
    • 标记了 ComponentCreator 的方法会将 DefaultUserService 注册到 IUserService 上,并使用 IOC / DI 中已注册的 ILangProvider 作为构造函数
    • 标记了 ReplaceCreator 的方法会将 IOC / DI 中已有的 ITestService 替换,并重新使用 SecondTestService 进行注册

    3.2 为你的类型加上 Component 让他们自动注册到 IOC / DI 容器中

    市面上有很多方便的 IOC / DI 工具库,但他们总是依赖手动注册。

    即使我们通过反射程序集,也很难做到对系统中所有有需要的程序集做反射 ( 我们肯定不会对 System 这种库进行反射注册的 )。

    但是通过 AppModule 以及对 ComponentScanAppModule 的依赖,我们可以很清楚的知道哪些程序集是需要进行反射注册的。

    AppSetup 会执行这些操作,

    而开发者们只需要为你们的类型加上 Component 特征即可

    [Component]
    public class DefaultUserService : IUserService
    {
    }

     注册方法有两种,通过 Component 的构造函数区分。

    • 注册为接口。在组件创建时,你必须使用接口类型进行创建
    • 注册为类型本身。在组件创建时,你必须使用类型进行创建

    你也可以同时注册为接口和其本身。

    3.3 编写你的配置类

    .Net 自带的 config 配置很好用,但是太臃肿,要写大量的映射类。

    Reface.AppStarter 简化这些复杂的过程,它只要你写一个配置类,然后再通过一个 json 反序列化就可以了。

    3.3.1 编写一个配置类

    任何数据结构你都可以直接当作配置类,不需要继承任何类,只要为其加上 Config 特征即可

    [Config("DbConnection")]
    public
    class DbConnectionConfig { public string ConnectionString { get; set; } }

    3.3.2 编写配制文件

    默认的配置文件路径是启动目录下的 app.json,

    所有标有 Config 特征的类都会从这里读取配置

    Config 中构造函数所要提供的字符串,就是配置文件中的 属性 名称

    {
        "DbConnection" : {
            "ConnectionString" : "Your Connection String Here"
        }
    }

    3.3.3 在该模块中添加对自动配置的依赖

    为你的 AppModule 添加特征 AutoConfigAppModule 即可。

    [AutoConfigAppModule]
    public class MyAppModule
    {
    }

     3.3.4 自定义配置文件路径 

    AppSetup 的构造函数中有一个参数,该参数就是配置文件的路径,你可以在 new AppSetup 的时候,指定一个新的配置文件路径。

     3.3.5 使用配置

    标有了 [Config] 的类型会以其自身的类型注册到 IOC / DI 容器中,

    因此,你可以通过 IOC / DI 的容器的自动装配功能得到它的实例。

    [Component]
    public class DefaultTestService
    {
        private readonly DbConnectionConfig config;
        
        public DefaultTestService(DbConnectionConfig config)
        {
            this.cofnig = config;
        }
    }

    4 系统中的 Attribute

    4.1 ScannableAttribute

    标记了该特征的类型将会在扫描时被记录,

    就如它的名字一样,它只表达一种允许被扫描的用意,没有其它任何含义,

    当你需要对某些类型进行分类时,请创建更有意义的特征,并继承此特征。

    4.2 ComponenAttribute

    标记了该特征的类型会被注册到 IOC / DI 容器中

    4.3 ConfigAttribute

    标记了该特征的类会从配置文件中进行反序列化,并以类型本身注册到 IOC / DI 容器中

    4.4 ListenerAttribute

    标记了该特征的类会成为一个事件总线的监听器

    4.5 CommandHandlerAttribute

    标记了该特征的类会成为一个命令总线的命令处理器

    4.6 ComponentCreatorAttribute

    在 AppModule 中,被标记了该特征的方法会将以方法的构建过程注册到 IOC / DI 容器中

    4.7 ReplacCreatorAttribute

    在 AppModule 中,被标记了该特征的方法会移除当前 IOC / DI 容器中的组件并重新注册,

    在一次构建中,同一个组件只可以被替换一次

    5 系统中的 AppModule

    5.1 ComponenScanAppModule

    该模块会将目标模块中所有标记了 ComponentAttribute 的组件注册到 IOC / DI 容器中

    5.2 AutoConfigAppModule

    该模块会将配置文件中的类型反序列化到目标模块中标记了 ConfigAttribute 的类型上,并注册到 IOC / DI 容器中


    后面的文章 

    • 如何使用事件总线
    • 如何使用命令总线
    • 如何编写功能性 AppModule
    • 什么是 AppContainer  

    相关链接

    本文为作者原创,转载请注明出处 : https://www.cnblogs.com/ShimizuShiori/p/12610668.html

  • 相关阅读:
    Chrome浏览器的下拉选择框option有黑框的问题
    修改input checkbox和radio默认样式
    VsCode安装cssrem插件实现px转rem
    js实现小球的弹性碰撞
    CSS 技巧 -- 不定宽溢出文本适配滚动
    记忆化递归和递推
    DOM事件中target和currentTarget的区别
    TypeScripy + Vue Property Decorator + Vue Router,组件内的导航守卫无效
    行内元素没有内容时设置默认的宽高
    焦点元素,添加半透明遮罩
  • 原文地址:https://www.cnblogs.com/ShimizuShiori/p/12610668.html
Copyright © 2011-2022 走看看