3

XAF新手入门 - 类型子系统(Types Info Subsystem) - haoxj

 1 year ago
source link: https://www.cnblogs.com/haoxj/p/16834882.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

类型子系统概述

类型子系统是XAF的核心概念,但我们平时却很少关注它,它集中存储了模块中的类型,它是生成应用程序模型(Application Model)的基础,它与XAF中其它的概念都有所关联,了解它可以使我们加深对XAF的理解。

类型子系统是什么

第一次接触类型子系统的小伙伴,应该感觉它与.NET中的类型系统是相似的,并且它中的一些接口与类与.NET类型系统也是对应的,如:ITypeInfo,IMemberInfo,IAssemblyInfo,是不是感觉很熟悉,其实XAF类型子系统就是对.NET类型系统的一个包装,并加入了一些XAF特有的功能,下面是XafApplication的构造函数。

image

TypesInfo是ITypesInfo的唯一派生类,它是类型子系统的核心,它提供了类型子系统的大部分功能,它也是类型子系统的代名词。

XafApplication构造函数中唯一需要传递的参数就是ITypesInfo,从这点也可以看出类型子系统在XAF中的重要性。TypesInfo的实例是通过XafTypesInfo以单例形式提供的(XafTypesInfo.Instance),需要注意在整个XAF项目中只有这一个TypesInfo实例,在不同的平台(WinForm与Blazor)下也是一样的,下面是XafTypesInfo创建TypesInfo实例的方法。

在XAF项目中的任何地方,你都可以直接使用XafTypesInfo.Instance访问到TypesInfo实例,在Blazor中ITypesInfo已被注入到容器中,你可以通过ServiceProvider.GetService<ITypesInfo>()获取TypesInfo实例,实际也是指向XafTypesInfo.Instance。

image

使用过XAF一段时间的小伙伴应该都知道XAF模块中的一些资源(BusinessObject、Controller等)都是通过反射(Reflection)方式进行收集的,而反射是有一定性能损耗的,如果在每次需要的时候都反射一次,系统的性能损耗会很大。TypesInfo会在XAF初始化时(Application.Setup),对模块(XAF模块)类库中的类型进行收集并缓存起来,不会对非模块类库进行收集,除非在Module类中进行了导出(如何导出非本模块中的类型,会在后续的章节中进行介绍)。

TypesInfo收集的类型(System.Type)会通过TypeInfo进行包装,类型的公共字段或属性是通过IMemberInfo进行包装,同时TypesInfo也提供了更加丰富的功能。在还没有深入了解TypesInfo之前,你可以简单的将TypesInfo理解为是对模块中类型的缓存,并提供了一些对缓存类型的操作方法(如:创建、更新、查找等)。

.NET中的反射常用于框架的开发,框架可以通过反射收集类型的信息,并通过这些类型信息辅助完成一些功能,XAF也是一个开发框架,TypesInfo承担了类型信息收集的角色,理所当然成了XAF的类型中心,其它功能模块就可以通过TypesInfo访问到自己所需的类型。

应用程序模型(Application Model)就是基于TypesInfo创建了模型中的Controller、Action、View等节点,关于应用程序模型,会在后面章节讲解。

DevExpress.ExpressApp.DC命名空间下包含了XAF类型子系统的主要类型,大家可以通过ILSpy等类似工具查看该命名空间下类型之间的依赖关系。

说一个小插曲,DC在XAF中就是DomainCompnent(域组件),ApplicationModel是基于DomainComponent的,BusinessObject中的NonPersistentObject也是基于DomainComponent的,在更早之前XPO有一个基于DomainComponent自动生成PersistentObject的功能(现在它已被弃用了),在这些DomainComponent当中,感觉ApplicationModel与XPO的DomainComponent很类似,都是基于接口的,NonPersistentObject只借用了DomainComponent这个概念,使用了DomainComponentAttribute,但在工作原理上与前两个有很大的区别。由于官方文档中没有关于它们之间关系的描述,以上的观点更多的只是个人的见解,有熟悉的小伙伴可以在评论区说说你的看法。

XAF是基于模型驱动的,模型是XAF的主线,模型在XAF中称为BusinessObject(有时也简称为BO),虽然TypesInfo存储了模块中的类型,但它大部分功能都是针对BusinessObject的。

TypesInfo实例中包含了一个PersistentTypes属性,虽然名字显示的是持久化类型,但其实它也包含了非持久化类型,而PersistentTypes的数据是由IEntityStore提供,TypesInfo中包含多个IEntityStore,下面是PersistentTypes的源码。

PersistentTypes中所有的类型都会在ApplicationModel中创建一个View节点。

image

官方文档中没有关于IEntityStore的介绍,与其相似的还有一个ITypeInfoSource,官方文档中也没有介绍,通过查看源码,大体知道了它们的含义,它们都有多个派生类,大部分都是重合的。虽然TypesInfo包含了所有类型,但都是放在一个缓存当中的,类型也有不同的分类,主要是想将持久化类型(XPO中的类型)与非持久化类型进行单独的存储,在这里持久化类型与非持久化类型它们统称为Entity,而派生自IEntityStore的类,就是用于分别存储不同类型的Entity,例如:XpoTypeInfoSource是负责存储XPO中的类型,NonPersistentTypeInfoSource是负责存储非持久化对象类型(NonPersistentObject),IEntityStore主要负责Entity类型的存储,而ITypeInfoSource在负责类型存储的同时,也提供了对类型的操作,你可以通过ILSpy工具查看它们的更多内容。

下面是TypesInfo的创建方法,前面已介绍过

image

在上面的代码中,我们可以看到TypesInfo会默认添加一个NonPersistentTypeInfoSource实例,在XAF初始化的过程中,还会添加一个XpoTypeInfoSource实例(这是默认情况下,如果你的系统中存在多个ObjectSpaceProvider,还会添加其它的)。

类型子系统能做什么

通过前面的介绍,我们知道TypesInfo可以为XAF功能模块提供所需的类型,也可以称为XAF的类型中心,官网提供了一个访问示例:https://docs.devexpress.com/eXpressAppFramework/113224/business-model-design-orm/types-info-subsystem/access-business-object-metadata

TypeInfo可以对成员(IMemberInfo)添加或修改,我们可以通过它来实现自定义TypeInfo,XAF提供了多种自定TypesInfo的方式,但我们一般会选择是在Module或Controller中,在Module或Controller中都是重写CustomizeTypesInfo方法,结果都是一样的,在选择上如果只会在某个Controller中调用,这样自定义与调用都放在一个Controller中会更加的直观,当然在Module中自定义会更加统一,这样你做了哪些自定义在Module中就能看到,这两种方式没有优劣,Controller中的自定义也只会调用一次。官网提供了一个CustomizeTypesInfo示例:https://docs.devexpress.com/eXpressAppFramework/113583/business-model-design-orm/types-info-subsystem/use-metadata-to-customize-business-classes-dynamically

本篇文章主要介绍了类型子系统的概念及在XAF中的作用,与其它XAF概念的结合及应用会在后面的章节中介绍。TypesInfo还有很多有用的属性与方法,想更加深入的了解,你还需要查阅官方文档,文档不全的可以结合源码。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK