allbetgaming官网:Reface.AppStarter 类型扫描 —— 获得项目中所有的实体类型

admin/2020-07-14/ 分类:科技/阅读:

类型扫描Reface.AppStarter 提供的最基本、最焦点的功效。

AutoConfig , ComponentScan 等功效都是基于该功效完成的。

每一个使用 Reface.AppStarter 的人都可以订制自己的扫描类型扫描逻辑。

例如

网络系统中所有的 实体 类型,并在系统启动后执行 Code-First 的相关操作。

我们现在就以该示例为需求,开发一个能够 扫描实体,并借助第三方框架实现 CodeFirst 的示例程序。

1. 建立程序

建立一个名为 Reface.AppStarter.Demos.ScanEntities 的控制台项目用于承载我们的示例程序。

2. 添加 Reface.AppStarter 的 nuget 依赖

点击接见 Reface.AppStarter @ nuget 可以复制最新版本的 Reface.AppStarter 的命令行到 Package Manager 中。

3. 建立专属的 Attribute

Reface.AppStarter 对类型的扫描是通过 Attribute 识别的。

Reface.AppStarter.Attributes.ScannableAttribute 示意该特征允许被 AppSetup 扫描并纪录。

因此只要将我们的 Attribute 继续于 ScannableAttribute 就可以被 AppSetup 扫描并纪录。

我们先建立一个目录 Attributes,并在该目录中建立特征类型 EntityAttribute 让其继续于 ScannableAttribute

using Reface.AppStarter.Attributes; namespace Reface.AppStarter.Demos.ScanEntities.Attributes { public class EntityAttribute : ScannableAttribute { } } 

所有标记了 EntityAttribute 的类型都市被 AppSetup 发现、纪录。

我们使用这些纪录就可以网络到系统内的所有实体,并进一步凭据这些实体类型举行 Code-First 操作。

4. 建立专属 AppModule

Reface.AppStarter 中对模块的依赖和增添都是通过 AppModule 完成的。

我们希望使用者添加对我们的 AppModule 依赖就可以扫描指定模块中的所有实体类型。

在应用时,我们希望形如下面的代码:

[ComponentScanAppModule] // IOC 组件扫描与注册模块 [AutoConfigAppModule] // 自动设置模块 [EntityScanAppModule] // 实体操作模块 public class UserAppModule : AppModule { } 

很明显,我们需要建立一个名为 EntityScanAppModule 的类型。

我们建立一个目录名为 AppModules,并将 EntityScanAppModule 建立在该目录下。

此时,我们的目录如下

- Reface.AppStarter.Demos.ScanEntities - AppModules EntityScanAppModule.cs - Attributes EntityAttribute.cs Program.cs 

此时的 EntityScanAppModule 是一个空缺的 AppModule
还不具有找到所有标记了 EntityAttribute 的类型的能力。

我们可以通过重写 OnUsing 方式赋予此功效。

OnUsing 方式具备一个类型为 AppModuleUsingArguments 的参数。

  • AppSetup , 此时启动历程的 AppSetup 实例
  • TargetAppModule , 以之前的 UserAppModule 为例,TargetAppModule 就是 UserAppModule 的实例
  • UsingAppModule , 以之前的 UserAppModule 为例,UsingAppModule 就是 EntityScanAppModule 的实例,也就是 this 指向的实例
  • ScannedAttributeAndTypeInfos , 从 TargetAppModule 中扫描所到的所有类型信息

看到最后一个属性,应该一切就简朴了。

ScannedAttributeAndTypeInfos 找到所有 AttributeEntityAttribute 的类型,就能解决了 :

using Reface.AppStarter.AppModules; using Reface.AppStarter.Demos.ScanEntities.Attributes; using System; using System.Collections.Generic; using System.Linq; namespace Reface.AppStarter.Demos.ScanEntities.AppModules { public class EntityScanAppModule : AppModule { public override void OnUsing(AppModuleUsingArguments args) { IEnumerable<Type> entityTypes = args .ScannedAttributeAndTypeInfos .Where(x => x.Attribute is EntityAttribute) .Select(x => x.Type); } } } 

我们现在需要思量的是,如何将 entityTypes 保留下来,以便在系统启动后使用它们建表。

除了使用 静态类 等常见手段保留这些信息,Reface.AppStarter 也提供了两种方式。

4.1 App 上下文

AppAppSetup.Start() 获得的实例。

App.Context 属性是一个 Dictionary<String, Object> 工具,允许开发者自定义一些信息挂载在上下文中,以便在其它位置使用它们。

AppSetup 在构建时代也可以预置一些信息到 App.Context 中。

public override void OnUsing(AppModuleUsingArguments args) { IEnumerable<Type> entityTypes = args .ScannedAttributeAndTypeInfos .Where(x => x.Attribute is EntityAttribute) .Select(x => x.Type); args.AppSetup .AppContext .GetOrCreate<List<Type>>("EntityTypes", key => { return new List<Type>(); }) .AddRange(entityTypes); } 

通过这种方式,当系统启动后,我们可以通过 App.Context 获得所有扫描到的实体类型:

var app = AppSetup.Start<XXXAppModule>(); List<Type> entityTypes = app.Context .GetOrCreate<List<Type>>("EntityTypes", key => new List<Type>()); // code-first here 

4.2 AppContainerBuilder / AppContainer

AppContainerApp 工具的组成要素,

App 的本质只有两样

  • 字典类型的上下文
  • 所有 AppContainer

每一种 AppContainer 都市治理某一类的类型,
而这些类型都是通过 ScannableAttribute 扫描获得的。

好比,在 Reface.AppStarter 中,有卖力 IOC 和卖力 AutoConfig 的两个 AppContainer
它们分别对标有 ComponentConfig 的类型举行差别的治理和处置。

凭据这个分门别类治理的头脑,所有的实体类型也应当由专门的 AppContainer 治理所有的 实体类型

5. 建立 EntityAppContainer

建立目录 AppContainers
并在目录内建立 EntityAppContainer
EntityAppContainer 需要继续 BaseAppContainer ,
添加组织函数,传入所有的 实体类型 ,
重写 OnAppStarted 方式 , 实现 Code-First 功效。

using Reface.AppStarter.AppContainers; using System; using System.Collections.Generic; namespace Reface.AppStarter.Demos.ScanEntities.AppContainers { public class EntityAppContainer : BaseAppContainer { // all entity type here private readonly IEnumerable<Type> entityType; public EntityAppContainer(IEnumerable<Type> entityType) { this.entityType = entityType; } public override void OnAppStarted(App app) { entityType.ForEach(x => Console.WriteLine("Do CODE-FIRST from type {0}", x)); } } } 

很明显,没有 entityType ,我们无法直接组织出 EntityAppContainer

Reface.AppStarter 要求所有的 AppContainer 都是通过 AppContainerBuilder 建立获得的。

AppContainer 差别,AppContainerBuilder 是被托管在 AppSetup 实例中的,
开发者可以通过 AppSetup 的实例 接见 指定类型的 AppContainerBuilder

AppContainerBuilder 一旦被 接见 ,就会马上建立,并在最终天生 App 实例时,构建成响应的 AppContainer 并移交给 App

6. 建立 EntityAppContainerBuilder

建立目录 AppContainerBuilders,
在目录内建立类型 EntityAppContainerBuilder 继续 BaseAppContainerBuilder,
并重写 Build 方式。

using Reface.AppStarter.AppContainerBuilders; using Reface.AppStarter.AppContainers; using System; namespace Reface.AppStarter.Demos.ScanEntities.AppContainerBuilders { public class EntityAppContainerBuilder : BaseAppContainerBuilder { public override IAppContainer Build(AppSetup setup) { throw new NotImplementedException(); } } } 

很明显,我们知道需要在 Build 中写下这样的代码

return new EntityAppContainer(entityTypes); 

entityTypes 从何而来?

这个就简朴了,为 EntityAppContainerBuilder 添加一个 AddEntityType(Type type) 就行了。

using Reface.AppStarter.AppContainerBuilders; using Reface.AppStarter.AppContainers; using Reface.AppStarter.Demos.ScanEntities.AppContainers; using System; using System.Collections.Generic; namespace Reface.AppStarter.Demos.ScanEntities.AppContainerBuilders { public class EntityAppContainerBuilder : BaseAppContainerBuilder { private readonly ICollection<Type> entityTypes; public EntityAppContainerBuilder() { entityTypes = new List<Type>(); } public void AddEntityType(Type type) { this.entityTypes.Add(type); } public override IAppContainer Build(AppSetup setup) { return new EntityAppContainer(entityTypes); } } } 

从这个类型不难发现,我们需要建立一个 EntityAppContainerBuilder ,并使用 AddEntityType 将实体类型加入。

最后的 Build 方式会由 AppSetup 内部执行。

7. 使用 EntityScanAppModule 操作 EntityAppContainerBuilder

现在回到之前的 EntityScanAppModule ,
早年向 App.Context 内预置信息的代码可以删除掉了。

我们先从 AppSetup 中获取 EntityAppContainerBuilder 的实例,
配合上 AddEntityType,然后就一气呵成了。

using Reface.AppStarter.AppModules; using Reface.AppStarter.Demos.ScanEntities.AppContainerBuilders; using Reface.AppStarter.Demos.ScanEntities.Attributes; using System.Linq; namespace Reface.AppStarter.Demos.ScanEntities.AppModules { public class EntityScanAppModule : AppModule { public override void OnUsing(AppModuleUsingArguments args) { EntityAppContainerBuilder builder = args.AppSetup.GetAppContainerBuilder<EntityAppContainerBuilder>(); args .ScannedAttributeAndTypeInfos .Where(x => x.Attribute is EntityAttribute) .Select(x => x.Type) .ForEach(x => builder.AddEntityType(x)); } } } 

8. 准备我们的启动程序

建立 DemoAppModule
添加一些 Entity,
添加 EntityScanAppModule 的依赖,
启动,即可测试我们的代码了。

using Reface.AppStarter.AppModules; using Reface.AppStarter.Demos.ScanEntities.AppModules; namespace Reface.AppStarter.Demos.ScanEntities { [EntityScanAppModule] public class DemoAppModule : AppModule { } } 

在 Program.cs 中编写启动程序

using System; namespace Reface.AppStarter.Demos.ScanEntities { class Program { static void Main(string[] args) { AppSetup.Start<DemoAppModule>(); Console.ReadLine(); } } } 

控制台中就可以获得所有的实体类型

Do CODE-FIRST from type Reface.AppStarter.Demos.ScanEntities.Entities.Role Do CODE-FIRST from type Reface.AppStarter.Demos.ScanEntities.Entities.User 

文中项目代码可以从这里下载 : Reface.AppStarter.Demos.ScanEntities @ Github

,

欧博开户网址

欢迎进入欧博开户网址(Allbet Gaming):www.aLLbetgame.us,欧博网址开放会员注册、代理开户、电脑客户端下载、苹果安卓下载等业务。

TAG:
阅读:
广告 330*360
广告 330*360

热门文章

HOT NEWS
  • 周榜
  • 月榜
Sunbet_进入申博sunbet官网
微信二维码扫一扫
关注微信公众号
新闻自媒体 Copyright © 2002-2019 Sunbet 版权所有
二维码
意见反馈 二维码