您的位置:首页 > 其它

XAF 转换不同应用程序模型

2011-01-13 08:36 609 查看
ConvertApplicationModelDifferences转换不同应用程序模型

eXpressAppFramework>Concepts>ApplicationModel>ConvertApplicationModelDifferences

TheeXpressAppFrameworkisbasedonthemodulesconcept.Asarule,everymoduleimplementsacertainfeature.Entitiesimplementedinamodule,suchaspersistentclassesorextraApplicationModelnodes-canbecustomizedbyusersoftheapplicationviatheModelEditor.SuchcustomizationsaresavedasApplicationModeldifferencesinXafMLfiles.LegacyApplicationModeldifferencesmightposeaproblemwhenamoduleisupdatedtoanewversion,anditsinternalstructureischanged.So,developersimplementingmodulesshouldprovidemeanstoconvertApplicationModeldifferenceswithnewversions.TheeXpressAppFrameworkprovideseasywaystoimplementsuchconverters.Thistopicdescribesthem.

eXpressApp框架基于模块构成。作为一个规则,每个模块实现一个特定功能。在一个模块中实现实体,如持久类或者用户应用程序可以通过模型编辑器定制其他应用程序模型节点。这种自定义保存不同应用程序模型在XafML文件中。当你升级一个模块是,可能不同应用程序模型会有问题,它的内部结构发生改变。因此,要实现转换新版本应用程序模型的差异部分。eXpressApp框架通过了非常容易的方法实现转换。本主题详细描述。

Basically,ApplicationModeldifferencesareconvertedintwosteps.
基本上,转换应用程序模型差异部分分两步。

TheXafMLfilesstoredinXMLformatcanbeprocessedbyamoduleimplementingtheIModelXmlConverterinterface.Thisstepallowstheapplicationtostartcorrectly,whereotherwise,legacyApplicationModeldifferenceswouldcauseanexceptionattheapplicationstart.Insimpleconversionscenarios,thismaybetheonlyrequiredstep.
XafML文件以XML文件格式存储,能被由实现IModelXmlConverter接口的模块处理。这个步骤可使应用程序正常启动,另外应用程序模型的差异可能导致应用程序在启动时异常。这是实现简单转换必须要做的步骤。
Forcomplexconversionscenarios,specialupdatersimplementingtheIModelNodeUpdater<T>interfaceshouldbeused.Suchupdaterscanperformmuchmoreversatileconversions.
复杂的转换,指定更新者实现IModelNodeUpdater<T>接口。这样的更新者可以实现更灵活的转换。

Dependingonaparticularscenario,youmayneedtoperformeitherbothofthesestepsorjustone.So,forexample,inonescenarioyoumayneedtoimplementanXMLconverter,sothattheapplicationcouldstart,andanodeupdater,toperformacomplexconversion.Inotherscenarios,youmayneedtoimplementonlyanXMLconverteroranodeupdater.

根据不同情况,你可能需要实现这两个步骤中一个或多个。例如,在一种情况下你可能需要实现一个XML转换,启动应用程序,一个节点更新,实现一个复杂转换。在其他情况下,你可能只需实现一个XML转换或一个节点更新。

ImplementanXMLconverter(实现一个XML转换)

AnXMLconverterisrepresentedbyamoduleimplementingtheIModelXmlConverterinterface.TheinterfacedeclarestheIModelXmlConverter.ConvertXmlmethod,whichisinvokedforeachnodecustomizedinApplicationModeldifferences.ThemethodtakestheConvertXmlParametersobject,supplyingdifferencesasaparameter.Youcanhandlechangestoanodeinthemethod'sbody,byconvertingdifferencesandmakingthemcorrespondtotheactualmodel.Considerthefollowingexample.

用一个模块实现IModelXmlConverter接口代表一个XML转换器。这个接口定义了IModelXmlConverter.ConvertXml方法,被用在应用程序模型差异部分的每个自定义节点。
该方法使用ConvertXmlParameters参数对象作为差异参数.你可以在方法内改变一个节点处理,通过转换差异使他们适应实际模型。参考下面例子。

SupposeyourapplicationusesamodulewhichaddsanOperatingModestringpropertytotheApplicationModel'sOptionsnode.Thispropertyisdesignedtotakeeithera"Simple"or"Complex"wordasavalue.Originally,themoduleextendstheApplicationModelinthefollowingway:

假设你用了一个应用程序给应用程序模型的选项节点添加一个字符串属性OperatingMode的模块,这个属性用“Simple”或“Complex”作为值。最初,这个模块同过以下方式扩展应用程序模型:

C#

VB

usingDevExpress.ExpressApp.Model;

publicinterfaceIModelMyOptions{

stringOperatingMode{get;set;}

}

publicsealedpartialclassMyModule:ModuleBase{

//...

publicoverridevoidExtendModelInterfaces(ModelInterfaceExtendersextenders){

base.ExtendModelInterfaces(extenders);

extenders.Add<IModelOptions,IModelMyOptions>();

}

}

ImportsDevExpress.ExpressApp.Model

PublicInterfaceIModelMyOptions

PropertyOperatingMode()AsString

EndInterface

PublicNotInheritablePartialClassMyModule

InheritsModuleBase

'...

PublicOverridesSubExtendModelInterfaces(ByValextendersAsModelInterfaceExtenders)

MyBase.ExtendModelInterfaces(extenders)

extenders.Add(OfIModelOptions,IModelMyOptions)()

EndSub

EndClass

C#

usingDevExpress.ExpressApp.Model;
publicinterfaceIModelMyOptions{
stringOperatingMode{get;set;}
}
publicsealedpartialclassMyModule:ModuleBase{
//...
publicoverridevoidExtendModelInterfaces(ModelInterfaceExtendersextenders){
base.ExtendModelInterfaces(extenders);
extenders.Add<IModelOptions,IModelMyOptions>();
}
}
VB

ImportsDevExpress.ExpressApp.Model
PublicInterfaceIModelMyOptions
PropertyOperatingMode()AsString
EndInterface
PublicNotInheritablePartialClassMyModule
InheritsModuleBase
'...
PublicOverridesSubExtendModelInterfaces(ByValextendersAsModelInterfaceExtenders)
MyBase.ExtendModelInterfaces(extenders)
extenders.Add(OfIModelOptions,IModelMyOptions)()
EndSub
EndClass
DX.Tabs.init('dxxTab175');
UsersofyourapplicationcustomizethispropertyvalueanditisstoredtotheirApplicationModeldifferences.Then,themoduleisupdatedtoanewversionwhichintroducesacoupleofchanges.First,theOperatingModepropertytypeischangedtoanewlyintroducedenumeration.Second,stringrepresentationsofthenewenumerationvaluesaredifferentfromthepreviouslyusedstringvalues:

应用程序的用户自定义这个属性值并存储到他们的应用程序模型差异。接着,模块更新到新版本改动。首先,OperatingMode属性类型更改为新进的枚举。第二,新的枚举字符串值不同于之前用的字符串值:

C#

VB

publicinterfaceIModelMyOptions{

OperatingModeOperatingMode{get;set;}

}

publicenumOperatingMode{Basic,Advanced}

PublicInterfaceIModelMyOptions

PropertyOperatingMode()AsOperatingMode

EndInterface

PublicEnumOperatingMode

Basic

Advanced

EndEnum

C#

publicinterfaceIModelMyOptions{
OperatingModeOperatingMode{get;set;}
}
publicenumOperatingMode{Basic,Advanced}
VB

PublicInterfaceIModelMyOptions
PropertyOperatingMode()AsOperatingMode
EndInterface
PublicEnumOperatingMode
Basic
Advanced
EndEnum
DX.Tabs.init('dxxTab176');
Ifyounowrecompiletheapplicationwiththeupdatedmoduleandredistributeit,existinguserswillnotbeabletousetheapplication.Attheapplicationstart,amessagewillbedisplayedstatingthatanerrorhasoccurredwhileloadingtheApplicationModeldifferences.Toavoidthis,anXMLconvertershouldbeimplementedinthemodule.Thefollowingcodesnippetillustratesapossiblesolution:

如果你用更新模块重新编辑应用程序并重新发布,已有的用户将不能用这个应用程序。在应用程序启动时,将显示一个信息,指出有错误发生,在加载应用程序模型差异。为了避免这个错误提示,应当在模块中实现一个XML转换器。下面代码说明一个可能的解决方案:

C#

VB

usingDevExpress.ExpressApp.Model;

usingDevExpress.ExpressApp.Updating;

publicsealedpartialclassMyModule:ModuleBase,IModelXmlConverter{

//...

publicvoidConvertXml(ConvertXmlParametersparameters){

if(typeof(IModelOptions).IsAssignableFrom(parameters.NodeType)){

stringproperty="OperatingMode";

if(parameters.ContainsKey(property)){

stringvalue=parameters.Values[property];

if(!Enum.IsDefined(typeof(OperatingMode),value)){

switch(value.ToLower()){

case"complex":

parameters.Values[property]=OperatingMode.Advanced.ToString();

break;

default:

parameters.Values[property]=OperatingMode.Basic.ToString();

break;

}

}

}

}

}

}

ImportsDevExpress.ExpressApp.Model

ImportsDevExpress.ExpressApp.Updating

PublicNotInheritablePartialClassMyModule

InheritsModuleBase

ImplementsIModelXmlConverter

'...

PublicSubConvertXml(ByValparametersAsConvertXmlParameters)

IfGetType(IModelOptions).IsAssignableFrom(parameters.NodeType)Then

Dim[property]AsString="OperatingMode"

Ifparameters.ContainsKey([property])Then

DimvalueAsString=parameters.Values([property])

If(NotSystem.Enum.IsDefined(GetType(OperatingMode),value))Then

SelectCasevalue.ToLower()

Case"complex"

parameters.Values([property])=OperatingMode.Advanced.ToString()

CaseElse

parameters.Values([property])=OperatingMode.Basic.ToString()

EndSelect

EndIf

EndIf

EndIf

EndSub

EndClass

C#

usingDevExpress.ExpressApp.Model;
usingDevExpress.ExpressApp.Updating;
publicsealedpartialclassMyModule:ModuleBase,IModelXmlConverter{
//...
publicvoidConvertXml(ConvertXmlParametersparameters){
if(typeof(IModelOptions).IsAssignableFrom(parameters.NodeType)){
stringproperty="OperatingMode";
if(parameters.ContainsKey(property)){
stringvalue=parameters.Values[property];
if(!Enum.IsDefined(typeof(OperatingMode),value)){
switch(value.ToLower()){
case"complex":
parameters.Values[property]=OperatingMode.Advanced.ToString();
break;
default:
parameters.Values[property]=OperatingMode.Basic.ToString();
break;
}
}
}
}
}
}
VB

ImportsDevExpress.ExpressApp.Model
ImportsDevExpress.ExpressApp.Updating
PublicNotInheritablePartialClassMyModule
InheritsModuleBase
ImplementsIModelXmlConverter
'...
PublicSubConvertXml(ByValparametersAsConvertXmlParameters)
IfGetType(IModelOptions).IsAssignableFrom(parameters.NodeType)Then
Dim[property]AsString="OperatingMode"
Ifparameters.ContainsKey([property])Then
DimvalueAsString=parameters.Values([property])
If(NotSystem.Enum.IsDefined(GetType(OperatingMode),value))Then
SelectCasevalue.ToLower()
Case"complex"
parameters.Values([property])=OperatingMode.Advanced.ToString()
CaseElse
parameters.Values([property])=OperatingMode.Basic.ToString()
EndSelect
EndIf
EndIf
EndIf
EndSub
EndClass
DX.Tabs.init('dxxTab177');
TheconvertercheckswhetherthecurrentlyprocessednodeistheOptionsnode.Ifitis,theconvertercheckswhethertheOperatingModepropertyhasalegacyvalue.Then,the"Complex"valuebecomesOperatingMode.AdvancedandallothervaluesbecomeOperatingMode.Basic.

这个转换器检查当前处理的节点是否是选项节点。如果是,他将检查OperatingMode是否有值。接着,"Complex"值变为OperatingMode.Advanced并且其他值变为OperatingMode.Basic

Now,consideranotherverycommonscenariowhenanode'spropertyisrenamed.Suppose,aModepropertydeclaredintheOptionsnodewasrenamedtoOperatingMode.ThefollowingcodesnippetillustratesapossibleXMLconverter:

现在,考虑另一种常用的情况,重命名一个节点的属性。假设,重命名一个定义在选项节点中模型属性。下面代码说明一个可能的XML转换器:

C#

VB

usingDevExpress.ExpressApp.Model;

usingDevExpress.ExpressApp.Updating;

publicsealedpartialclassMyModule:ModuleBase,IModelXmlConverter{

//...

publicvoidConvertXml(ConvertXmlParametersparameters){

if(typeof(IModelOptions).IsAssignableFrom(parameters.NodeType)){

stringoldProperty="Mode";

stringnewProperty="OperatingMode";

if(parameters.ContainsKey(oldProperty)){

parameters.Values[newProperty]=parameters.Values[oldProperty];

parameters.Values.Remove(oldProperty);

}

}

}

}

ImportsDevExpress.ExpressApp.Model

ImportsDevExpress.ExpressApp.Updating

PublicNotInheritablePartialClassMyModule

InheritsModuleBase

ImplementsIModelXmlConverter

'...

PublicSubConvertXml(ByValparametersAsConvertXmlParameters)

IfGetType(IModelOptions).IsAssignableFrom(parameters.NodeType)Then

DimoldPropertyAsString="Mode"

DimnewPropertyAsString="OperatingMode"

Ifparameters.ContainsKey(oldProperty)Then

parameters.Values(newProperty)=parameters.Values(oldProperty)

parameters.Values.Remove(oldProperty)

EndIf

EndIf

EndSub

EndClass

Private<ModCod

C#

usingDevExpress.ExpressApp.Model;
usingDevExpress.ExpressApp.Updating;
publicsealedpartialclassMyModule:ModuleBase,IModelXmlConverter{
//...
publicvoidConvertXml(ConvertXmlParametersparameters){
if(typeof(IModelOptions).IsAssignableFrom(parameters.NodeType)){
stringoldProperty="Mode";
stringnewProperty="OperatingMode";
if(parameters.ContainsKey(oldProperty)){
parameters.Values[newProperty]=parameters.Values[oldProperty];
parameters.Values.Remove(oldProperty);
}
}
}
}
VB

ImportsDevExpress.ExpressApp.Model
ImportsDevExpress.ExpressApp.Updating
PublicNotInheritablePartialClassMyModule
InheritsModuleBase
ImplementsIModelXmlConverter
'...
PublicSubConvertXml(ByValparametersAsConvertXmlParameters)
IfGetType(IModelOptions).IsAssignableFrom(parameters.NodeType)Then
DimoldPropertyAsString="Mode"
DimnewPropertyAsString="OperatingMode"
Ifparameters.ContainsKey(oldProperty)Then
parameters.Values(newProperty)=parameters.Values(oldProperty)
parameters.Values.Remove(oldProperty)
EndIf
EndIf
EndSub
EndClass
Private<ModCod
DX.Tabs.init('dxxTab178');
Asillustratedbytheexamples,anXMLconverterworkswithonenodeatatime.So,complexconversions,affectingseveralnodesatonce,arenotpossible.Inthesecases,specialupdatersimplementingtheIModelNodeUpdater<T>interfaceshouldbeused.

用例子说明,一个XML转换器一次由一个节点工作。接着,复杂的转换,不可能一次影响几个节点。在这种情况下,应当用指定的更新器实现IModelNodeUpdater<T>接口。

ImplementaNodeUpdater(属性一个节点更新器)

AnodeupdaterisrepresentedbyaclassimplementingtheIModelNodeUpdater<T>interface.Thegenerictypeparameterspecifiesthetypeofthenodesforwhichtheupdaterisintended.TheinterfacedeclaresasingleIModelNodeUpdater<T>.UpdateNodemethod,whichtakestwoparameters.ThefirstparameteristheApplicationModelnodeinprocess,representedbyanobjectimplementingtheIModelNodeinterface.Thesecondparameteristheapplication'sApplicationModel,representedbyanobject,implementingtheIModelApplicationinterface.SinceyouhaveaccesstothewholeApplicationModel,complexconversionsaffectingmultiplenodescanbeperformed.Considerthefollowingexample.

一个节点更新器表示一个类实现IModelNodeUpdater<T>接口。更新者的目的是泛型参数类型指定节点的类型。该接口定义一个IModelNodeUpdater<T>.UpdateNode方法,有两个参数。第一个参数是应用程序模型节点在处理过程中。表示一个对象实现了IModelNode接口。第二个参数是应用程序的应用程序模型,由一个对象实现IModelApplication接口。既然你已经访问整个应用程序模型,执行影响多个节点的复杂转换。看下面例子。

SupposeyourapplicationusesamodulewhichaddsanOperatingModestringpropertytotheApplicationModel'sOptionsnode.Originally,theinterfaceextendingtheApplicationModellookslikethis:

假设你用了一个应用程序给应用程序模型的选项节点添加一个字符串属性OperatingMode的模块,最初,接口扩展应用程序模型如下:

C#

VB

publicinterfaceIModelMyOptions{

OperatingModeOperatingMode{get;set;}

}

publicenumOperatingMode{Basic,Advanced}

PublicInterfaceIModelMyOptions

PropertyOperatingMode()AsOperatingMode

EndInterface

PublicEnumOperatingMode

Basic

Advanced

EndEnum

C#

publicinterfaceIModelMyOptions{
OperatingModeOperatingMode{get;set;}
}
publicenumOperatingMode{Basic,Advanced}
VB

PublicInterfaceIModelMyOptions
PropertyOperatingMode()AsOperatingMode
EndInterface
PublicEnumOperatingMode
Basic
Advanced
EndEnum
DX.Tabs.init('dxxTab179');
Then,themoduleisupdatedtoanewversionwhichmovesthepropertytoanewlyintroducedchildnode:

然后,模组更新到一个新的版本,移动到新推出的子节点的属性:

C#

VB

usingDevExpress.ExpressApp.Model;

publicinterfaceIModelMyOptions{

IModelChildOptionsChildOptions{get;}

}

publicinterfaceIModelChildOptions:IModelNode{

OperatingModeOperatingMode{get;set;}

}

publicenumOperatingMode{Basic,Advanced}

ImportsDevExpress.ExpressApp.Model

PublicInterfaceIModelMyOptions

ReadOnlyPropertyChildOptions()AsIModelChildOptions

EndInterface

PublicInterfaceIModelChildOptions

InheritsIModelNode

PropertyOperatingMode()AsOperatingMode

EndInterface

PublicEnumOperatingMode

Basic

Advanced

EndEnum

C#

usingDevExpress.ExpressApp.Model;
publicinterfaceIModelMyOptions{
IModelChildOptionsChildOptions{get;}
}
publicinterfaceIModelChildOptions:IModelNode{
OperatingModeOperatingMode{get;set;}
}
publicenumOperatingMode{Basic,Advanced}
VB

ImportsDevExpress.ExpressApp.Model
PublicInterfaceIModelMyOptions
ReadOnlyPropertyChildOptions()AsIModelChildOptions
EndInterface
PublicInterfaceIModelChildOptions
InheritsIModelNode
PropertyOperatingMode()AsOperatingMode
EndInterface
PublicEnumOperatingMode
Basic
Advanced
EndEnum
DX.Tabs.init('dxxTab180');
Ifyounowrecompiletheapplicationwiththeupdatedmoduleandredistributeit,theoriginalOperatingModepropertyvaluesspecifiedbyusersoftheapplicationwillbelost.Toavoidthis,anodeupdatershouldbeimplemented.Apossibleplacefortheimplementationistheupdatedmodule:

如果你用更新模块重新编辑应用程序并重新发布,已有的用户将不能用这个应用程序。原来OperatingMode所指定的属性值将会丢失应用程序的用户。为了避免这种情况,应当实现一个节点更新器。更新模块可能用一下方法实现。

C#

VB

usingDevExpress.ExpressApp.Model;

usingDevExpress.ExpressApp.Model.Core;

publicsealedpartialclassMyModule:ModuleBase,IModelNodeUpdater<IModelOptions>{

//...

publicvoidUpdateNode(IModelOptionsnode,IModelApplicationapplication){

stringmyProperty="OperatingMode";

if(node.HasValue(myProperty)){

stringvalue=node.GetValue<string>(myProperty);

node.ClearValue(myProperty);

((IModelMyOptions)node).ChildOptions.OperatingMode=

(OperatingMode)Enum.Parse(typeof(OperatingMode),value);

}

}

}

ImportsDevExpress.ExpressApp.Model

ImportsDevExpress.ExpressApp.Model.Core

PublicNotInheritablePartialClassMyModule

InheritsModuleBase

ImplementsIModelNodeUpdater(OfIModelOptions)

'...

PublicSubUpdateNode(ByValnodeAsIModelOptions,ByValapplicationAsIModelApplication)

DimmyPropertyAsString="OperatingMode"

Ifnode.HasValue(myProperty)Then

DimvalueAsString=node.GetValue(OfString)(myProperty)

node.ClearValue(myProperty)

CType(node,IModelMyOptions).ChildOptions.OperatingMode=_

CType(System.Enum.Parse(GetType(OperatingMode),value),OperatingMode)

EndIf

EndSub

EndClass

C#

usingDevExpress.ExpressApp.Model;
usingDevExpress.ExpressApp.Model.Core;
publicsealedpartialclassMyModule:ModuleBase,IModelNodeUpdater<IModelOptions>{
//...
publicvoidUpdateNode(IModelOptionsnode,IModelApplicationapplication){
stringmyProperty="OperatingMode";
if(node.HasValue(myProperty)){
stringvalue=node.GetValue<string>(myProperty);
node.ClearValue(myProperty);
((IModelMyOptions)node).ChildOptions.OperatingMode=
(OperatingMode)Enum.Parse(typeof(OperatingMode),value);
}
}
}
VB

ImportsDevExpress.ExpressApp.Model
ImportsDevExpress.ExpressApp.Model.Core
PublicNotInheritablePartialClassMyModule
InheritsModuleBase
ImplementsIModelNodeUpdater(OfIModelOptions)
'...
PublicSubUpdateNode(ByValnodeAsIModelOptions,ByValapplicationAsIModelApplication)
DimmyPropertyAsString="OperatingMode"
Ifnode.HasValue(myProperty)Then
DimvalueAsString=node.GetValue(OfString)(myProperty)
node.ClearValue(myProperty)
CType(node,IModelMyOptions).ChildOptions.OperatingMode=_
CType(System.Enum.Parse(GetType(OperatingMode),value),OperatingMode)
EndIf
EndSub
EndClass
DX.Tabs.init('dxxTab181');
TheupdaterintheexamplecheckswhetherthecurrentlyprocessednodehasalegacyOperatingModepropertyvalue.Ifthereissuchavalue,itisassignedtothenewOperatingModeproperty,andthelegacypropertyvalueiscleared.

在实例中检查是否当前处理节点有一个OperatingMode属性值。如果有值,它被标识为新的OperatingMode属性并清除之前的值。

Notethatsinceanodeupdatercanbeimplementedanywhereintheapplication,theupdatershouldberegisteredviatheModuleBase.AddModelNodeUpdatersmethod:

注意,一个节点的更新可以在任何应用程序实现,这个更新者应该通过ModuleBase.AddModelNodeUpdaters方法注册:

C#

VB

usingDevExpress.ExpressApp.Model;

usingDevExpress.ExpressApp.Model.Core;

publicsealedpartialclassMyModule:ModuleBase,IModelNodeUpdater<IModelOptions>{

//...

publicoverridevoidAddModelNodeUpdaters(IModelNodeUpdaterRegistratorupdaterRegistrator){

base.AddModelNodeUpdaters(updaterRegistrator);

updaterRegistrator.AddUpdater<IModelOptions>(this);

}

}ImportsDevExpress.ExpressApp.Model

ImportsDevExpress.ExpressApp.Model.Core

PublicNotInheritablePartialClassMyModule

InheritsModuleBase

ImplementsIModelNodeUpdater(OfIModelOptions)

'...

PublicOverridesSubAddModelNodeUpdaters(_

ByValupdaterRegistratorAsIModelNodeUpdaterRegistrator)

MyBase.AddModelNodeUpdaters(updaterRegistrator)

updaterRegistrator.AddUpdater(OfIModelOptions)(Me)

EndSub

EndClass

C#

usingDevExpress.ExpressApp.Model;
usingDevExpress.ExpressApp.Model.Core;
publicsealedpartialclassMyModule:ModuleBase,IModelNodeUpdater<IModelOptions>{
//...
publicoverridevoidAddModelNodeUpdaters(IModelNodeUpdaterRegistratorupdaterRegistrator){
base.AddModelNodeUpdaters(updaterRegistrator);
updaterRegistrator.AddUpdater<IModelOptions>(this);
}
}
VB

ImportsDevExpress.ExpressApp.Model
ImportsDevExpress.ExpressApp.Model.Core
PublicNotInheritablePartialClassMyModule
InheritsModuleBase
ImplementsIModelNodeUpdater(OfIModelOptions)
'...
PublicOverridesSubAddModelNodeUpdaters(_
ByValupdaterRegistratorAsIModelNodeUpdaterRegistrator)
MyBase.AddModelNodeUpdaters(updaterRegistrator)
updaterRegistrator.AddUpdater(OfIModelOptions)(Me)
EndSub
EndClass
欢迎转载,转载请注明出处:http://www.cnblogs.com/Tonyyang/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: