C# WPF MVVM开发框架Caliburn.Micro 自定义Conventions⑩
處理自定義約定
雖然ViewLocator和ViewModelLocator類通過提供對每個(gè)類的NameTransformer實(shí)例的公共訪問來支持非標(biāo)準(zhǔn)約定,但對于那些不熟悉正則表達(dá)式語法的人來說,添加基于正則表達(dá)式的新名稱轉(zhuǎn)換規(guī)則可能是一項(xiàng)艱巨的任務(wù)。此外,由于NameTransformer設(shè)計(jì)用于執(zhí)行通用名稱轉(zhuǎn)換,因此它不允許單獨(dú)定制名稱和名稱空間轉(zhuǎn)換。換句話說,沒有簡單的方法可以在維護(hù)名稱空間的標(biāo)準(zhǔn)轉(zhuǎn)換的同時(shí)添加對自定義視圖名稱后綴的支持,也沒有簡單的方法可以在維護(hù)類型名稱的標(biāo)準(zhǔn)轉(zhuǎn)換的同時(shí)更改名稱空間轉(zhuǎn)換。認(rèn)識(shí)到這些局限性,我們?yōu)槊總€(gè)定位器類添加了可配置性和幾個(gè)高級方法。這些新特性允許為常見用例構(gòu)建自定義轉(zhuǎn)換規(guī)則,而無需了解正則表達(dá)式。此外,這些方法是領(lǐng)域感知的(即它們考慮了名稱空間和類型名稱的概念),而不是面向泛型名稱轉(zhuǎn)換。
術(shù)語
在介紹定位器類的這些新方法之前,最好先討論一下術(shù)語。
名稱轉(zhuǎn)換是一個(gè)通用術(shù)語,用于描述如何進(jìn)行類型解析。類型的完全限定名作為源,然后“轉(zhuǎn)換”為輸出類型的名稱。在最低級別,NameTransformer類負(fù)責(zé)此操作,并使用基于正則表達(dá)式的“轉(zhuǎn)換規(guī)則”執(zhí)行轉(zhuǎn)換。
類型映射是一個(gè)術(shù)語,用于描述添加到定位器類中的新功能。創(chuàng)建類型映射被認(rèn)為是更高級別的操作,因?yàn)轭愋陀成淇紤]類型解析的兩個(gè)方面:解析類型的名稱和解析類型的命名空間。盡管類型映射最終被表示為NameTransformer的轉(zhuǎn)換規(guī)則,但是創(chuàng)建類型映射的方法除了更特定于域之外,還可以使您不必理解正則表達(dá)式。
類型映射的配置
這兩個(gè)定位器類都可以通過調(diào)用新的ConfigureTypeMappings()方法進(jìn)行配置,該方法將TypeMappingConfiguration類的實(shí)例作為參數(shù)。
類型映射配置類
此類具有各種屬性,其值用作定位器類配置各種高級類型映射方法行為所需的全局設(shè)置。
Properties
DefaultSubNamespaceForViews:包含應(yīng)用程序視圖的子名稱空間(即命名空間“MyProject.Views”中的“視圖”)。此值用于為ViewModels創(chuàng)建具有子名稱空間的默認(rèn)映射。默認(rèn)值為“視圖”。
DefaultSubNamespaceForViewModels:包含應(yīng)用程序的ViewModels的子命名空間(即命名空間“MyProject.ViewModels”中的“ViewModels”)。此值用于為視圖創(chuàng)建具有子名稱空間的默認(rèn)映射。默認(rèn)值為“ViewModels”。
UseNameSuffixesInMappings:指示映射是否應(yīng)考慮類型名稱中的名稱后綴以區(qū)分視圖和視圖模型的標(biāo)志。如果可以通過命名空間或子命名空間空間來區(qū)分視圖和ViewModels,則可以將此值設(shè)置為false。默認(rèn)值為true。
NameFormat:用于使用基名稱(或?qū)嶓w名稱)和視圖或視圖模型后綴構(gòu)造類型名稱的格式字符串。格式項(xiàng)目如下:
{0}:基名稱
{1} :名稱后綴
由于只有兩個(gè)參數(shù)將與指定的格式字符串一起使用,NameFormat可以包含上面列出的格式項(xiàng)的任何組合,但不能再包含任何組合(即{2}、{3}等)。默認(rèn)值為“{0}{1}”(即<basename><suffix>)。
INCLUDEVIEWUFFIXIVIEWMODELNAME:指示映射是否應(yīng)將“頁面”或“表單”等名稱后綴作為伴生視圖模型名稱的一部分的標(biāo)志(例如CustomerPageViewModel與CustomerServiceWModel或CustomerPerformViewModel與CustomerServiceWModel)。請注意,按照慣例,無論此屬性的值如何,如果視圖后綴是ViewModel后綴的一部分,則假定忽略視圖后綴(即CustomerViewModel而不是CustomerViewModel)。默認(rèn)值為true。
ViewSuffixList:在配置期間為其創(chuàng)建默認(rèn)類型映射的視圖后綴列表。默認(rèn)值為“視圖”和“頁面”。
ViewModelSuffix:用于所有類型映射的ViewSuffix,包括配置期間添加的默認(rèn)類型映射以及配置之后添加的自定義類型映射。默認(rèn)值為“ViewModel”。
ViewLocator.ConfigureTypeMapping(), ViewModelLocator.ConfigureTypeMapping() Methods
此方法配置或重新配置定位器類添加類型映射的方式。
public static void ConfigureTypeMapping(TypeMappingConfiguration config)config參數(shù)是一個(gè)配置對象,其屬性值用作配置類型映射的定位器類的設(shè)置。
locator類使用TypeMappingConfiguration類的默認(rèn)屬性值在內(nèi)部調(diào)用此方法。
每次調(diào)用此方法時(shí),都會(huì)清除現(xiàn)有的名稱轉(zhuǎn)換規(guī)則,并自動(dòng)添加新的默認(rèn)類型映射。
配置對象的設(shè)置全局應(yīng)用于在配置時(shí)自動(dòng)添加的默認(rèn)類型映射和配置后添加的任何類型映射。例如,如果對NameFormat進(jìn)行了自定義,以指定將名稱后綴放在基名稱之前的命名約定,從而將名稱后綴轉(zhuǎn)換為前綴(例如ViewCustomer和ViewModelCustomer),則此約定將用作對添加類型映射的方法的任何后續(xù)調(diào)用的標(biāo)準(zhǔn)類型命名約定
//Override the default subnamespaces var config = new TypeMappingConfiguration {DefaultSubNamespaceForViewModels = "MyViewModels",DefaultSubNamespaceForViews = "MyViews" };ViewLocator.ConfigureTypeMappings(config); ViewModelLocator.ConfigureTypeMappings(config);//Resolves: //MyProject.MyViewModels.CustomerViewModel -> MyProject.MyViews.CustomerView //MyProject.MyViewModels.CustomerPageViewModel -> MyProject.MyViews.CustomerPage //MyProject.MyViews.CustomerView -> MyProject.MyViewModels.CustomerViewModel //MyProject.MyViews.CustomerPage -> MyProject.MyViewModels.CustomerPageViewModel//Change ViewModel naming convention to always exclude View suffix var config = new TypeMappingConfiguration {DefaultSubNamespaceForViewModels = "MyViewModels",DefaultSubNamespaceForViews = "MyViews",IncludeViewSuffixInViewModelNames = false };ViewLocator.ConfigureTypeMappings(config); ViewModelLocator.ConfigureTypeMappings(config);//Resolves: //MyProject.MyViewModels.CustomerViewModel -> MyProject.MyViews.CustomerPage, MyProject.MyViews.CustomerView //MyProject.MyViews.CustomerView -> MyProject.MyViewModels.CustomerViewModel //MyProject.MyViews.CustomerPage -> MyProject.MyViewModels.CustomerViewModel//Change naming conventions to place name suffixes before the base name (i.e. name prefix) var config = new TypeMappingConfiguration {NameFormat = "{1}{0}",IncludeViewSuffixInViewModelNames = false };ViewLocator.ConfigureTypeMappings(config); ViewModelLocator.ConfigureTypeMappings(config);//Resolves: //MyProject.ViewModels.ViewModelCustomer -> MyProject.Views.PageCustomer, MyProject.Views.ViewCustomer //MyProject.Views.ViewCustomer -> MyProject.ViewModels.ViewModelCustomer //MyProject.Views.PageCustomer -> MyProject.ViewModels.ViewModelCustomer//Change naming conventions to omit name suffixes altogether (i.e. distinguish View and ViewModel types by namespace alone) var config = new TypeMappingConfiguration {UseNameSuffixesInMappings = false };ViewLocator.ConfigureTypeMappings(config); ViewModelLocator.ConfigureTypeMappings(config);//Resolves: //MyProject.ViewModels.Customer -> MyProject.Views.Customer //MyProject.Views.Customer -> MyProject.ViewModels.Customer//Configure for Spanish language and semantics var config = new TypeMappingConfiguration() {DefaultSubNamespaceForViewModels = "ModelosDeVistas",DefaultSubNamespaceForViews = "Vistas",ViewModelSuffix = "ModeloDeVista",ViewSuffixList = new List<string>(new string[] { "Vista", "Pagina" }),NameFormat = "{1}{0}",IncludeViewSuffixInViewModelNames = false };ViewLocator.ConfigureTypeMappings(config); ViewModelLocator.ConfigureTypeMappings(config);//Resolves: //MiProyecto.ModelosDeVistas.ModeloDeVistaCliente -> MiProyecto.Vistas.VistaCliente, MiProyecto.Vistas.PaginaCliente //MiProyecto.Vistas.VistaCliente -> MiProyecto.ModelosDeVistas.ModeloDeVistaCliente //MiProyecto.Vistas.PaginaCliente -> MiProyecto.ModelosDeVistas.ModeloDeVistaClienteNew Type Mapping Methods
ViewLocator.AddDefaultTypeMapping(), ViewModelLocator.AddDefaultTypeMapping()
此方法用于添加類型映射,該映射支持給定視圖名稱后綴的標(biāo)準(zhǔn)類型和命名空間命名約定。
public static void AddDefaultTypeMapping(string viewSuffix = "View")viewSuffix參數(shù)是類型名稱的后綴。應(yīng)該是“視圖”或“視圖”的同義詞。(可選)
此方法主要用于添加對具有自定義同義詞(例如“表單”、“屏幕”、“選項(xiàng)卡”)但使用標(biāo)準(zhǔn)命名約定的類型的支持。
雖然viewSuffix參數(shù)是可選的,默認(rèn)為“View”,但沒有必要以這種方式調(diào)用此方法,因?yàn)槎ㄎ黄黝愐呀?jīng)為“View”和“Page”視圖名稱后綴添加了類型映射,盡管如果定位器類使用ConfigureTypeMappings()方法和修改TypeMappingConfiguration對象的ViewSuffixList屬性進(jìn)行了不同的配置,則情況可能并非如此。但是,修改配置對象的ViewSuffixList屬性并重新配置locator類可以避免事后調(diào)用此方法。
請記住,如果配置對象的UseNameSuffixesInMappings屬性設(shè)置為false,則此方法不會(huì)添加任何類型映射。在這種情況下,沒有為其添加映射的默認(rèn)類型命名約定。
//Add support for "Form" as a synonym of "View" using the standard type and namespace naming conventions ViewLocator.AddDefaultTypeMapping("Form"); //Resolves: MyProject.ViewModels.MainFormViewModel -> MyProject.Views.MainFormViewModelLocator.AddDefaultTypeMapping("Form"); //Resolves: MyProject.Views.MainForm -> MyProject.ViewModels.MainFormViewModelViewLocator.RegisterViewSuffix()
此方法用于向ViewLocator指示使用NameTransformer.AddRule()添加了支持自定義視圖后綴的轉(zhuǎn)換規(guī)則。調(diào)用AddNamespaceMapping()、AddTypeMapping()和AddDefaultTypeMapping()類型映射方法時(shí),ViewLocator類會(huì)自動(dòng)在內(nèi)部調(diào)用此方法。
public static void RegisterViewSuffix(string viewSuffix)viewSuffix參數(shù)是類型名稱的后綴。應(yīng)該是“視圖”或“視圖”的同義詞。(可選)
為了使多視圖支持正常工作,ViewLocator需要跟蹤應(yīng)用程序可能使用的所有視圖后綴。盡管在使用新的類型映射方法添加名稱轉(zhuǎn)換規(guī)則時(shí)會(huì)自動(dòng)管理此操作,但直接通過ViewLocator類的NameTransformer實(shí)例添加的轉(zhuǎn)換規(guī)則將繞過此注冊步驟。因此,在這種情況下需要調(diào)用ViewLocator.RegisterViewSuffix()。在添加新條目之前,該方法將對現(xiàn)有條目執(zhí)行檢查。
//Manually add a rule to the NameTransformer to do simple text replacement independent of namespace ViewLocator.NameTransformer.AddRule("ScreenViewModel$", "Screen"); //However, we need to treat "Screen" as a synonym of "View" somehow in order to //enable multi-view support for View types with names ending in "Screen" ViewLocator.RegisterViewSuffix("Screen"); //Resolves: MyProject.ViewModels.CustomerScreenViewModel -> MyProject.Views.Customer.Master //when the context is "Master"ViewLocator.AddNamespaceMapping(),ViewModelLocator.AddNamespaceMapping()
此方法用于在源命名空間和一個(gè)或多個(gè)目標(biāo)命名空間之間添加類型映射。結(jié)果類型映射創(chuàng)建了一個(gè)轉(zhuǎn)換規(guī)則,該規(guī)則支持標(biāo)準(zhǔn)類型命名約定,但具有自定義命名空間命名約定。或者,可以為此映射指定自定義視圖后綴。
public static void AddNamespaceMapping(string nsSource, string[] nsTargets, string viewSuffix = "View")nsSource:源類型的命名空間
nsTargets:作為數(shù)組的目標(biāo)類型的名稱空間
viewSuffix:類型名稱的后綴。應(yīng)該是“視圖”或“視圖”的同義詞。(可選)
public static void AddNamespaceMapping(string nsSource, string nsTarget, string viewSuffix = "View")nsSource:源類型的命名空間
nsTarget:目標(biāo)類型的命名空間
viewSuffix:類型名稱的后綴。應(yīng)該是“視圖”或“視圖”的同義詞。(可選)
此方法支持在nsSource參數(shù)中使用通配符(用*)。當(dāng)nsSource參數(shù)使用空字符串(或string.Empty)時(shí),作為nsTarget/nsTargets參數(shù)傳遞的命名空間將追加到源類型的命名空間。有關(guān)更多詳細(xì)信息,請參閱示例。
可以將數(shù)組作為目標(biāo)命名空間的參數(shù)傳遞,以指示目標(biāo)類型可以存在于多個(gè)命名空間中(“一對多”映射)。由于定位器類被設(shè)計(jì)為拾取與名稱轉(zhuǎn)換規(guī)則匹配的類型的第一個(gè)匹配項(xiàng),因此,如果某個(gè)類型實(shí)際上不存在于某個(gè)目標(biāo)名稱空間中,或者不同名稱空間中存在多個(gè)共享同一名稱的類型,則無所謂。此機(jī)制的一個(gè)可能用例是將ViewModel命名空間映射到自定義視圖的程序集和標(biāo)準(zhǔn)視圖的另一個(gè)程序集。如果自定義視圖的部件不存在,或者自定義視圖部件中不存在特定視圖,則ViewLocator將從標(biāo)準(zhǔn)視圖部件中拾取視圖。
//"Append target to source" mapping //Null string or string.Empty passed as source namespace is special case to allow this //Note the need to prepend target namespace with "." to make this work ViewLocator.AddNamespaceMapping("", ".Views"); //Resolves: MyProject.Customers.CustomerViewModel -> MyProject.Customers.Views.CustomerView//Standard explicit namespace mapping ViewLocator.AddNamespaceMapping("MyProject.ViewModels.Customers", "MyClient1.Views"); //Resolves: MyProject.ViewModels.CustomerViewModel -> MyClient1.Views.CustomerView//One to many explicit namespace mapping ViewLocator.AddNamespaceMapping("MyProject.ViewModels.Customers", new string[] { "MyClient1.Views", "MyProject.Views" } ); //Resolves: MyProject.ViewModels.CustomerViewModel -> {MyClient1.Views.CustomerView, MyProject.Views.CustomerView }//Wildcard mapping ViewLocator.AddNamespaceMapping("*.ViewModels.Customers.*", "MyClient1.Customers.Views"); //Resolves: MyProject.ViewModels.Customers.CustomerViewModel -> MyClient1.Customers.Views.CustomerView // MyProject.More.ViewModels.Customers.MasterViewModel -> MyClient1.Customers.Views.MasterView // MyProject.ViewModels.Customers.More.OrderHistoryViewModel -> MyClient1.Customers.Views.OrderHistoryViewViewLocator.AddSubNamespaceMapping(),ViewModelLocator.AddSubNamespaceMapping()
此方法用于通過將給定的子名稱空間替換為另一子名稱空間,在源名稱空間和一個(gè)或多個(gè)目標(biāo)名稱空間之間添加類型映射。結(jié)果類型映射創(chuàng)建了一個(gè)轉(zhuǎn)換規(guī)則,該規(guī)則支持標(biāo)準(zhǔn)類型命名約定,但具有自定義命名空間命名約定。或者,可以為此映射指定自定義視圖后綴。
public static void AddSubNamespaceMapping(string nsSource, string[] nsTargets, string viewSuffix = "View")nsSource:源類型的子名稱空間
nsTargets:目標(biāo)類型為數(shù)組的子名稱空間
viewSuffix:類型名稱的后綴。應(yīng)該是“視圖”或“視圖”的同義詞。(可選)
public static void AddSubNamespaceMapping(string nsSource, string nsTarget, string viewSuffix = "View")nsSource:源類型的子名稱空間
nsTarget:目標(biāo)類型的子名稱空間
viewSuffix:類型名稱的后綴。應(yīng)該是“視圖”或“視圖”的同義詞。(可選)
此方法支持在nsSource參數(shù)中使用通配符(用*)。當(dāng)nsSource參數(shù)使用空字符串(或string.Empty)時(shí),作為nsTarget/nsTargets參數(shù)傳遞的命名空間將追加到源類型的命名空間。當(dāng)nsSource為空字符串或以通配符開頭和結(jié)尾時(shí),其行為與AddNamespaceMapping()的行為相同。與AddNamespaceMapping()一樣,AddSubNamespaceMapping()方法支持一對多映射。有關(guān)說明,請參閱AddNamespaceMapping()的說明。
此方法在配置時(shí)為配置對象的ViewSuffixList中的每個(gè)視圖后綴在內(nèi)部調(diào)用。由DefaultSubNamespaceForViews和DefaultSubNamespaceForViewModels指定的子名稱用于映射。如果不需要“視圖”和“ViewModels”子名稱空間之間的默認(rèn)映射,則可以使用適當(dāng)?shù)呐渲迷O(shè)置來消除直接調(diào)用AddSubNamespaceMapping()的需要。
//Add support for Spanish namespaces ViewLocator.AddSubNamespaceMapping("ModelosDeVistas", "Vistas"); //Resolves: MiProyecto.ModelosDeVistas.Clientes.ClienteViewModel -> MiProyecto.Vistas.Clientes.ClienteViewViewModelLocator.AddSubNamespaceMapping("Vistas", "ModelosDeVistas"); //Resolves: MiProyecto.Vistas.Clientes.ClienteView -> MiProyecto.ModelosDeVistas.Clientes.ClienteViewModel//Wildcard subnamespace mapping ViewLocator.AddSubNamespaceMapping("*.ViewModels", "ExtLib.Views"); //Resolves: MyCompany.MyApp.SomeNamespace.ViewModels.CustomerViewModel -> ExtLib.Views.CustomerViewViewLocator.AddSubNamespaceMapping("ViewModels.*", "Views"); //Resolves: MyApp.ViewModels.Some.Name.Space.CustomerViewModel -> MyApp.Views.CustomerViewViewLocator.AddSubNamespaceMapping("MyApp.*.ViewModels", "ExtLib.Views"); //Resolves: MyCompany.MyApp.SomeNamespace.ViewModels.CustomerViewModel -> MyCompany.ExtLib.Views.CustomerViewViewLocator.AddTypeMapping(),ViewModelLocator.AddTypeMapping()
此方法用于添加表示為基于正則表達(dá)式的轉(zhuǎn)換的類型映射。結(jié)果類型映射創(chuàng)建了一個(gè)轉(zhuǎn)換規(guī)則,該規(guī)則支持標(biāo)準(zhǔn)類型命名約定,但具有自定義命名空間命名約定。或者,可以為此映射指定自定義視圖后綴。
public static void AddTypeMapping(string nsSourceReplaceRegEx, string nsSourceFilterRegEx, string[] nsTargetsRegEx, string viewSuffix = "View")nsSourceReplaceRegEx:源命名空間的RegEx替換模式
nsSourceFilterRegEx:源命名空間的正則表達(dá)式篩選器模式
nsTargetsRegEx:目標(biāo)命名空間的RegEx替換值數(shù)組
viewSuffix:類型名稱的后綴。應(yīng)該是“視圖”或“視圖”的同義詞。(可選)
public static void AddTypeMapping(string nsSourceReplaceRegEx, string nsSourceFilterRegEx, string nsTargetRegEx, string viewSuffix = "View")nsSourceReplaceRegEx:源命名空間的RegEx替換模式
nsSourceFilterRegEx:源命名空間的正則表達(dá)式篩選器模式
nsTargetsRegEx:目標(biāo)命名空間的RegEx替換值
viewSuffix:類型名稱的后綴。應(yīng)該是“視圖”或“視圖”的同義詞。(可選)
有關(guān)創(chuàng)建基于正則表達(dá)式的轉(zhuǎn)換規(guī)則的詳細(xì)信息,請參閱NameTransformer上的文檔。與通過NameTransformer類添加轉(zhuǎn)換規(guī)則不同,此方法將命名空間轉(zhuǎn)換與類型名轉(zhuǎn)換分離。此外,它還支持一對多命名空間映射。有關(guān)說明,請參閱AddNamespaceMapping()的說明。
//Capture namespace fragment preceding "ViewModels." as "nsbefore" string subns = RegExHelper.NamespaceToRegEx("ViewModels."); string rxrep = RegExHelper.GetNamespaceCaptureGroup("nsbefore") + subns;//Output the namespace fragment after "Views." in the target namespace string rxtgt = @"Views.${nsbefore}"; ViewLocator.AddTypeMapping(rxrep, null, rxtgt); //Resolves: MyApp.Some.Name.Space.ViewModels.TestViewModel -> Views.MyApp.Some.Name.Space.TestView02
—
最后
原文標(biāo)題:Caliburn.Micro Xaml made easy
原文鏈接:https://caliburnmicro.com/documentation/custom-conventions
翻譯:dotnet編程大全
C#技術(shù)群?:?添加小編微信mm1552923,備注:進(jìn)群!
總結(jié)
以上是生活随笔為你收集整理的C# WPF MVVM开发框架Caliburn.Micro 自定义Conventions⑩的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 再见 Typora,这款 Markdow
- 下一篇: C# 是否可以将 动态或匿名类型 转成