您的位置:首页 > 其它

XAF 领域组件基础

2011-01-15 15:50 225 查看
DomainComponentsBasics(领域组件基础)

eXpressAppFramework>Concepts>BusinessModelDesign>DomainComponents>DomainComponentsBasics

DomainComponentstechnologyisdesignedtosimplifydatamanagementandreusabilitybyprovidingamuchmoreflexibleandabstractedapproachtobusinessobjectdesign.Youcancomposeanapplicationfromreusableblocks,abstractedawayfromaparticularpersistencelayer.
领域模型组件技术用于设计简单的数据管理和通过提供一个更灵活和抽象的方法复用业务对象设计。你可以制作一个用于程序从可重用块,一个特定的持久层抽象方法。

WithDomainComponentsyoudefineinterfacesinsteadofregularbusinessobjectsinheritedfromXPOclasses.Theseinterfaceswilldeclarerequiredpropertiesordatafields.Thewaythisdataistobeprocessed(DomainLogic)isthendefinedbycreatingspecialclassesthatdeterminehowinterfacemembersbehavewhenanobjectisconstructed,whenpropertiesarechanged,etc.ActualbusinessclassesareautomaticallyimplementedbyXAFatruntimebasedontheprovidedlogicandinterfaces.Youcanpackageinterfacesanddomainlogicinanassemblyanduseitasadomainlibrary.IfyouthencreateanewXAFapplication,youcanreferencethedomainlibraryandreusethedomaincomponents.Sinceinterfacessupportmultipleinheritance,therequiredbusinessobjectscanbecombinedintonewdomaincomponents.Withinterfaces,youcanmakeyourdomainmodelindependentofimplementation.

用领域组件定义接口代替从XPO类继承的常规业务对象。这些接口定义所需的属性或数据字段。这种方式处理(域逻辑)数据,然后建立特殊类定义以决定接口成员的如何行为当构建一个对象,一个属性更改,等等。实际业务类自动实现通过XAF在运行时基于提供的逻辑和接口。你可以打包接口和域逻辑在一个程序集中,用它作为一个域库。如果接下来你创建一个新的XAF应用程序,你可以引用域库,重用域组件。由于接口支持多继承,你可以实现自己独立域模型。

BenefitsoftheDomainComponentsTechnology

域组件技术的好处

DomainComponentsTechnologyisnotbyanymeansareplacementfortheregularbusinessclassesapproachtodefiningdomainentities.Themainadvantageofthetechnologyistheabilitytocreatereusabledomainlibrariescontainingcomponentsthatcanbecombinedinanyway.Ifyoudonotneedtheabilitytocreatereusablecomponentsandcombinethem,mostprobablyyouwillnotneedtouseDomainComponents.ThefollowinglistdescribesthebenefitsoftheDomainComponentstechnologyandshouldhelpyoudecidewhetherornottheapproachisrightforyourtask.
域组件技术无论如何都不能定义为常规业务类方法定义域实体的替代品。该技术的优势是能建立重用以任何方式组合的包含组件的域库。如果你不需要能建立可重用和组合他们,最有可能你不需要用域组件。下面描述域组件技术的好处,帮助你决定你的任务是否使用该技术。

·Youcancreatereusabledomainlibraries.(可以建立可重用的域库)

Mostprobably,eachnewXAFapplicationyoudevelopisnotunique.Themostcommonobjects,suchas,Person,Phone,Address,etc.arealwaysused.TheBusinessClassLibraryprovidesyouwithasetofclassesthatyouwillneedmostfrequently.But,implementingyourownreusablelibraryisnotasimpletask.WithDomainComponentsyoucaneasilypackageanassemblyandreferenceitinyourapplications.
通常,开发的每个新的XAF应用程序都是独特的。常见的对象,如人员,电话号码,地址等等。业务类库提供一组经常使用的类。但是实现你自己可重用的库是不那么简单的任务。用域组件技术你可以很容易包装一个程序集并在应用程序中引用它。

·Youcanusemultipleinheritance.(你可以用多继承)

SinceDomainComponentsarerepresentedbyinterfacesandnotbyclasses,youcanusemultipleinheritancetocombineseveralpreviouslydefinedcomponentsintoanewone.ThenewDomainComponentwillexposethepropertiesofallitsancestorsandutilizetheirDomainLogic.Ofcourseyoucanaddnewpropertiesandapplyadditionallogic.
由于域组件是通过接口展现而不是通过类,你可以用多继承来组合几个之前定义的组件成一个新的组件。新的领域构件公开所有祖先和可用领域逻辑的属性。当然,可以添加新的属性和额外应用逻辑。

·YoudonotneedtoinheritfromBasePersistentClasseswhenimplementingDomainComponents.(实现一个域组件不用从基持久类继承)

EachregularbusinessclassisderivedfromoneoftheBasePersistentClassesinXAF.Thebehavioroftheseclassesdiffers.Forinstance,abaseclasscaneitherexposetheauto-generatedprimarykeypropertyofanintegerorGuidtypeornot..Thechoiceofthebaseclassismadeonceaclassisimplemented.WiththeDomainComponents,youcanuseaspecificbaseclassineachnewscenario(seetheITypesInfo.AddEntityToGeneratemethodoverloadthattakesthebaseClassparameter).However,attributesapplicabletoregularbusinessclassesandtheirpropertiescanalsobeusedwithDomainComponents.Andofcourse,theobjectimplementedviaDomainComponentsdoesnotdifferfromtheobjectimplementedinastandardwayfromtheend-userorapplicationadministratorpointofview.

在XAF中,每个常规业务类是基于一个基持久类。这些类的行为不同。例如,一个基类也能公开自动生成的整数或Guid或不类型的属性。选择的基类一次实现一个类。用领域构件,在每一个方案(见ITypesInfo.AddEntityToGenerate方法覆写用baseClass参数)中你可以用一个指定的基类。然而,特性适用于日常业务类和他们的属性,也适用于领域构件。当然,通过领域构件实现对象不同于从终端用户或应用程序管理员视点用一个标准方法实现对象。

DefinitionoftheDomainComponentsInterfaces(定义域组件接口)

ThefollowingsnippetillustratesatypicalDomainComponentdefinition.

下面代码片段说明了一个典型的领域构件定义。

C#

VB

[DomainComponent]

publicinterfaceIPerson{

stringLastName{get;set;}

stringFirstName{get;set;}

stringFullName{get;}

voidCopy(IPersontarget);

}

<DomainComponent>_

PublicInterfaceIPerson

PropertyLastName()AsString

PropertyFirstName()AsString

ReadOnlyPropertyFullName()AsString

SubCopy(ByValtargetAsIPerson)

EndInterface

C#

[DomainComponent]
publicinterfaceIPerson{
stringLastName{get;set;}
stringFirstName{get;set;}
stringFullName{get;}
voidCopy(IPersontarget);
}
VB

<DomainComponent>_
PublicInterfaceIPerson
PropertyLastName()AsString
PropertyFirstName()AsString
ReadOnlyPropertyFullName()AsString
SubCopy(ByValtargetAsIPerson)
EndInterface
DX.Tabs.init('dxxTab131');
Asyoucanseeinthecodeabove,theinterfacedecoratedwiththeDomainComponentAttributeisconsideredtobeaDomainComponent.Thisinterfacemustexposepropertiesofthebusinessclasstobeautomaticallygeneratedwhentheapplicationruns.Youcanuseattributesapplicabletoregularbusinessclassesandtheirproperties.Forinstance,youcandecoratetheLastNamepropertywiththeRuleRequiredFieldAttributeandtheclassitselfwiththeNavigationItemAttribute.Notetheread-onlyFullNamepropertyandtheCopymethod.Asthesemembervaluesshouldbecalculated,itisrequiredtoimplementtheDomainLogic,describinghowtogetthesemembers'values.

正如你从上面代码看到,领域构件用特性DomainComponentAttribute修饰。当应用程序运行时这个接口公开了自动生成业务类的属性。你可以用使用与日常业务类和他们属性的特性。例如,你用特性RuleRequiredFieldAttribute修饰LastName属性,用特性NavigationItemAttribute修饰所在类。注意只读FullName属性和复制方法。这些成员的值是计算得到,它需要实现领域逻辑,描述如何获取这些成员的值。

Note(备注)

YoucanusetheDomainComponentv.10.2templatetosimplifythedefinitionoftheDomainComponentanditslogic.
你可以用领域构件V10.2模板简化领域构件定义和他的逻辑。

ImplementationoftheDomainLogicClasses(实现域逻辑类)

EachDomainComponentcanhaveoneormoreDomainLogics.EachDomainLogicisrepresentedbyaclass.Generally,thisclassshouldbedecoratedwiththeDomainLogicAttribute,whichindicatestheDomainComponentinterfacetowhichthetargetclassbelongs(theDomainComponentinterfacetypeisdefinedbytheattribute'sDomainLogicAttribute.InterfaceTypeparameter).TheDomainLogicclassshouldexposemethodsnamedaccordingtothefollowingnamingconventions.

每个领域构件有一个或多个域逻辑。每个域逻辑代表一个类。通常,这个类用特性DomainLogicAttribute修饰,指出这个领域构件接口上的目标类归属(领域构件接口通过特性的DomainLogicAttribute.InterfaceType参数定义)。这些领域逻辑公开以下命名约定的命名方法。

MethodName(方法名称)

Description(描述)

Get_PropertyName

Executedwhengettingatargetpropertyvalue.Atargetpropertyshouldberead-only.Youcanusethismethodtoimplementcalculatedproperties.

执行时得到一个目标属性的值。目标属性只读。可以用这个方法实现计算属性。

Init_PropertyName

Executedwhenatargetpropertyisinitialized.Atargetpropertyshouldnotberead-only.Youcanusethismethodtospecifytheinitialvalueofaproperty.

执行时目标属性被初始化。目标属性不能只读。可以用着方法初始化一个属性的值。

AfterChange_PropertyName

Executedafteratargetpropertyischanged.Atargetpropertyshouldnotberead-only.Youcanusethismethodtoimplementdependentproperties.

执行后改变一个目标属性。目标属性不能只读。可以用这个方法属性实现依赖属性。

MethodName

Executedwhenthetargetmethodiscalled.Youcanusethismethodtodefinethetargetmethodbody.

执行时目标方法被调用。你可以用这个方法定义一个目标方法体。

AfterConstruction

Executedafteranobjectisconstructed.Youcanusethismethodinsteadofthepreviousonetoinitializeseveralpropertiesatonce.

执行后构建一个对象。你可以用这个方法一次初始化几个属性而不是之前那个方法。

Note(备注)

Thesemethodsshouldbepublicandshouldaccepttheobjectofthetargetinterfacetypeasthefirstparameter.PropertyNameandMethodNameshouldbesubstitutedwiththetargetmembers'names.

这些方式是公共的,接受目标接口类型对象作为第一个参数。PropertyName和MethodName应该用目标成员的名称替代。

Asyoucanseefromthetableabove,methodnamescanconsistofthetargetpropertynameandoneofthefollowingprefixes:AfterChange_,Get_orInit_.Additionally,thereistheAfterConstructionpredefinedmethodname.YoucandefineadditionalmethodsthatcanbecalledfrommethodsimplementingtheDomainLogic.

正如你从上面表看到的,方法名称有目标属性名称和AfterChange_,Get_或者Init_前缀组成。另外,AfterConstruction是预定义方法名称。你可以定义其他能被实现领域逻辑方法调用的方法。

ThefollowingsnippetillustratesDomainLogicclassimplementation.

下面代码片段说明实现领域逻辑

C#

VB

[DomainLogic(typeof(IPerson))]

publicclassPersonLogic{

publicstaticstringGet_FullName(IPersonperson){

returnstring.Format("{0}{1}",person.FirstName,person.LastName);

}

publicstaticvoidCopy(IPersonperson,IPersontarget){

if(target!=null){

target.FirstName=person.FirstName;

target.LastName=person.LastName;

}

}

}

<DomainLogic(GetType(IPerson))>_

PublicClassPersonLogic

PublicSharedFunctionGet_FullName(ByValpersonAsIPerson)AsString

ReturnString.Format("{0}{1}",person.FirstName,person.LastName)

EndFunction

PublicSharedSubCopy(ByValpersonAsIPerson,ByValtargetAsIPerson)

IftargetIsNotNothingThen

target.FirstName=person.FirstName

target.LastName=person.LastName

EndIf

EndSub

EndClass

C#

[DomainLogic(typeof(IPerson))]
publicclassPersonLogic{
publicstaticstringGet_FullName(IPersonperson){
returnstring.Format("{0}{1}",person.FirstName,person.LastName);
}
publicstaticvoidCopy(IPersonperson,IPersontarget){
if(target!=null){
target.FirstName=person.FirstName;
target.LastName=person.LastName;
}
}
}
VB

<DomainLogic(GetType(IPerson))>_
PublicClassPersonLogic
PublicSharedFunctionGet_FullName(ByValpersonAsIPerson)AsString
ReturnString.Format("{0}{1}",person.FirstName,person.LastName)
EndFunction
PublicSharedSubCopy(ByValpersonAsIPerson,ByValtargetAsIPerson)
IftargetIsNotNothingThen
target.FirstName=person.FirstName
target.LastName=person.LastName
EndIf
EndSub
EndClass
DX.Tabs.init('dxxTab132');
Youcanalsodefineamethod,inaDomainComponent,thatwillcreateDomainComponentinstances.Forthispurpose,themethodmustbeparameterless,havetherequiredreturntypeandbedecoratedwiththeCreateInstanceAttribute.
你也可以在领域构件内定义一个方法,将创建领域构件实例。为此,这个方法必须无参数,具备必要的返回类并用CreateInstanceAttribute修饰。

C#

VB

[DomainComponent]

publicinterfaceIAddressable{

stringPrimaryAddress{get;set;}

stringSecondaryAddress{get;set;}

}

[DomainComponent]

publicinterfaceIPerson{

IAddressableAddress{get;set;}

[CreateInstance]

IAddressableCreateAddress();

}

[DomainLogic(typeof(IPerson))]

publicclassPersonLogic{

publicstaticvoidAfterConstruction(IPersonperson){

if(person.Address==null){

person.Address=person.CreateAddress();

}

}

}

<DomainComponent>_

PublicInterfaceIAddressable

PropertyPrimaryAddress()AsString

PropertySecondaryAddress()AsString

EndInterface

<DomainComponent>_

PublicInterfaceIPerson

PropertyAddress()AsIAddressable

<CreateInstance>_

FunctionCreateAddress()AsIAddressable

EndInterface

<DomainLogic(GetType(IPerson))>_

PublicClassPersonLogic

PublicSharedSubAfterConstruction(ByValpersonAsIPerson)

Ifperson.AddressIsNothingThen

person.Address=person.CreateAddress()

EndIf

EndSub

EndClass

C#

[DomainComponent]
publicinterfaceIAddressable{
stringPrimaryAddress{get;set;}
stringSecondaryAddress{get;set;}
}
[DomainComponent]
publicinterfaceIPerson{
IAddressableAddress{get;set;}
[CreateInstance]
IAddressableCreateAddress();
}
[DomainLogic(typeof(IPerson))]
publicclassPersonLogic{
publicstaticvoidAfterConstruction(IPersonperson){
if(person.Address==null){
person.Address=person.CreateAddress();
}
}
}
VB

<DomainComponent>_
PublicInterfaceIAddressable
PropertyPrimaryAddress()AsString
PropertySecondaryAddress()AsString
EndInterface
<DomainComponent>_
PublicInterfaceIPerson
PropertyAddress()AsIAddressable
<CreateInstance>_
FunctionCreateAddress()AsIAddressable
EndInterface
<DomainLogic(GetType(IPerson))>_
PublicClassPersonLogic
PublicSharedSubAfterConstruction(ByValpersonAsIPerson)
Ifperson.AddressIsNothingThen
person.Address=person.CreateAddress()
EndIf
EndSub
EndClass
DX.Tabs.init('dxxTab133');

Note(备注)

IfyouhavenoaccesstotheDomainLogicclasssources,youcanusetheITypesInfo.RegisterDomainLogicandITypesInfo.UnregisterDomainLogicmethodstomanipulatetheDomainLogicassignment.
如果你不访问领域逻辑类资源,你可以用ITypesInfo.RegisterDomainLogic和ITypesInfo.UnregisterDomainLogic方法使领域自己工作。

RegisteringtheDomainComponentsintheXAFApplication(XAF应用程序中注册域组件)

Tospecifywhatclassesshouldbegenerated,registerrequireddomaincomponentswiththeapplication.OverridetheModuleBase.SetupmethodandinvoketheITypesInfo.AddEntityToGeneratemethodinit:

要指定类生成什么,需要在应用程序中指出所需的领域构件。覆写ModuleBase.Setup方法并调用ITypesInfo.AddEntityToGenerate方法。

C#

VB

usingDevExpress.Persistent.BaseImpl;

//...

publicoverridevoidSetup(XafApplicationapplication){

if(!XafTypesInfo.IsInitialized){

XafTypesInfo.Instance.AddEntityToGenerate("Person",typeof(IPerson),typeof(BaseObject));

//...

}

base.Setup(application);

}

ImportsDevExpress.Persistent.BaseImpl

'...

PublicOverridesSubSetup(ByValapplicationAsXafApplication)

If(NotXafTypesInfo.IsInitialized)Then

XafTypesInfo.Instance.AddEntityToGenerate("Person",GetType(IPerson),GetType(BaseObject))

'...

EndIf

MyBase.Setup(application)

EndSub

C#

usingDevExpress.Persistent.BaseImpl;
//...
publicoverridevoidSetup(XafApplicationapplication){
if(!XafTypesInfo.IsInitialized){
XafTypesInfo.Instance.AddEntityToGenerate("Person",typeof(IPerson),typeof(BaseObject));
//...
}
base.Setup(application);
}
VB

ImportsDevExpress.Persistent.BaseImpl
'...
PublicOverridesSubSetup(ByValapplicationAsXafApplication)
If(NotXafTypesInfo.IsInitialized)Then
XafTypesInfo.Instance.AddEntityToGenerate("Person",GetType(IPerson),GetType(BaseObject))
'...
EndIf
MyBase.Setup(application)
EndSub
DX.Tabs.init('dxxTab134');
Withthecodeabove,thePersonclassderivedfromtheBaseObjectclasswillbegenerated.ThegeneratedclasswillexposepropertiesandutilizetheDomainLogicoftheIPersonDomainComponent.
有以上代码,将生成派生于BaseObject类的Person。这个生成的类利用IPerson领域构件的领域逻辑公开属性。

CurrentLimitations(当前限制)

AstheDomainComponentstechnologyisreleasedasapreviewinXAFv2010vol1,thereareseveralissuesandlimitations.DomainComponentscannotbeused:

领域构件技术作为预览版发布在XAFv2010vol1,有一些问题和局限。不能用领域构件:

InaMediumTrustenvironment.(在一个中级信任环境)
WiththeTreeListEditorsModule.(用树列表编辑模块)
WiththeSchedulerModule.(用计划模块)

However,theseissueswillbefixedassoonaspossible.(不过,这些问题可能不久将被解决)

ToseeafullexampleonhowtodefineDomainComponents,specifytheDomainLogicandregisterthemintheXAFapplication;refertotheHowto:ImplementDomainComponentstopic.

看完整的如何调用领域构件的例子,在XAF应用程序中指定领域构件和注册他们;请参考如何实现领域构件主题

Note(备注)

TheXCRMdemoinstalledwithXAFisacustomerrelationshipmanagementapplicationthatusestheDomainComponentstechnologyandiscomposedcompletelyofreusableblocks,abstractedawayfromaparticularpersistencelayer.TheapplicationislocatedintheC:\Users\Public\Documents\DevExpress2010.2Demos\eXpressAppFramework\XCRMfolderbydefault.ToseehowvarioustaskscanbeimplementedviaDomainComponents,takealookatthesourcecodeofthisapplication.

XCRM演示同XAF一起安装,是一个自定义关系管理应用程序,用了领域构件技术,完全可重用的模块组成,从一个特定的持久层抽象出来。默认,这个应用程序在本地C:\Users\Public\Documents\DevExpress2010.2Demos\eXpressAppFramework\XCRM文件夹。要了解实现各自任务通过领域构件,请看应用程序源代码。

欢迎转载,转载请注明出处:http://www.cnblogs.com/Tonyyang/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: