前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C# WPF MVVM开发框架Caliburn.Micro 自定义Conventions⑩

C# WPF MVVM开发框架Caliburn.Micro 自定义Conventions⑩

作者头像
用户9127601
发布2022-01-13 08:54:44
6330
发布2022-01-13 08:54:44
举报
文章被收录于专栏:dotNET编程大全dotNET编程大全

处理自定义约定

虽然ViewLocator和ViewModelLocator类通过提供对每个类的NameTransformer实例的公共访问来支持非标准约定,但对于那些不熟悉正则表达式语法的人来说,添加基于正则表达式的新名称转换规则可能是一项艰巨的任务。此外,由于NameTransformer设计用于执行通用名称转换,因此它不允许单独定制名称和名称空间转换。换句话说,没有简单的方法可以在维护名称空间的标准转换的同时添加对自定义视图名称后缀的支持,也没有简单的方法可以在维护类型名称的标准转换的同时更改名称空间转换。认识到这些局限性,我们为每个定位器类添加了可配置性和几个高级方法。这些新特性允许为常见用例构建自定义转换规则,而无需了解正则表达式。此外,这些方法是领域感知的(即它们考虑了名称空间和类型名称的概念),而不是面向泛型名称转换。

术语

在介绍定位器类的这些新方法之前,最好先讨论一下术语。

名称转换是一个通用术语,用于描述如何进行类型解析。类型的完全限定名作为源,然后“转换”为输出类型的名称。在最低级别,NameTransformer类负责此操作,并使用基于正则表达式的“转换规则”执行转换。

类型映射是一个术语,用于描述添加到定位器类中的新功能。创建类型映射被认为是更高级别的操作,因为类型映射考虑类型解析的两个方面:解析类型的名称和解析类型的命名空间。尽管类型映射最终被表示为NameTransformer的转换规则,但是创建类型映射的方法除了更特定于域之外,还可以使您不必理解正则表达式。

类型映射的配置

这两个定位器类都可以通过调用新的ConfigureTypeMappings()方法进行配置,该方法将TypeMappingConfiguration类的实例作为参数。

类型映射配置类

此类具有各种属性,其值用作定位器类配置各种高级类型映射方法行为所需的全局设置。

Properties

DefaultSubNamespaceForViews:包含应用程序视图的子名称空间(即命名空间“MyProject.Views”中的“视图”)。此值用于为ViewModels创建具有子名称空间的默认映射。默认值为“视图”。

DefaultSubNamespaceForViewModels:包含应用程序的ViewModels的子命名空间(即命名空间“MyProject.ViewModels”中的“ViewModels”)。此值用于为视图创建具有子名称空间的默认映射。默认值为“ViewModels”。

UseNameSuffixesInMappings:指示映射是否应考虑类型名称中的名称后缀以区分视图和视图模型的标志。如果可以通过命名空间或子命名空间空间来区分视图和ViewModels,则可以将此值设置为false。默认值为true。

NameFormat:用于使用基名称(或实体名称)和视图或视图模型后缀构造类型名称的格式字符串。格式项目如下:

{0}:基名称

{1} :名称后缀

由于只有两个参数将与指定的格式字符串一起使用,NameFormat可以包含上面列出的格式项的任何组合,但不能再包含任何组合(即{2}、{3}等)。默认值为“{0}{1}”(即<basename><suffix>)。

INCLUDEVIEWUFFIXIVIEWMODELNAME:指示映射是否应将“页面”或“表单”等名称后缀作为伴生视图模型名称的一部分的标志(例如CustomerPageViewModel与CustomerServiceWModel或CustomerPerformViewModel与CustomerServiceWModel)。请注意,按照惯例,无论此属性的值如何,如果视图后缀是ViewModel后缀的一部分,则假定忽略视图后缀(即CustomerViewModel而不是CustomerViewModel)。默认值为true。

ViewSuffixList:在配置期间为其创建默认类型映射的视图后缀列表。默认值为“视图”和“页面”。

ViewModelSuffix:用于所有类型映射的ViewSuffix,包括配置期间添加的默认类型映射以及配置之后添加的自定义类型映射。默认值为“ViewModel”。

ViewLocator.ConfigureTypeMapping(), ViewModelLocator.ConfigureTypeMapping() Methods

此方法配置或重新配置定位器类添加类型映射的方式。

代码语言:javascript
复制
public static void ConfigureTypeMapping(TypeMappingConfiguration config)

config参数是一个配置对象,其属性值用作配置类型映射的定位器类的设置。

locator类使用TypeMappingConfiguration类的默认属性值在内部调用此方法。

每次调用此方法时,都会清除现有的名称转换规则,并自动添加新的默认类型映射。

配置对象的设置全局应用于在配置时自动添加的默认类型映射和配置后添加的任何类型映射。例如,如果对NameFormat进行了自定义,以指定将名称后缀放在基名称之前的命名约定,从而将名称后缀转换为前缀(例如ViewCustomer和ViewModelCustomer),则此约定将用作对添加类型映射的方法的任何后续调用的标准类型命名约定

代码语言:javascript
复制
//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.ModeloDeVistaCliente

New Type Mapping Methods

ViewLocator.AddDefaultTypeMapping(), ViewModelLocator.AddDefaultTypeMapping()

此方法用于添加类型映射,该映射支持给定视图名称后缀的标准类型和命名空间命名约定。

代码语言:javascript
复制
public static void AddDefaultTypeMapping(string viewSuffix = "View")

viewSuffix参数是类型名称的后缀。应该是“视图”或“视图”的同义词。(可选)

此方法主要用于添加对具有自定义同义词(例如“表单”、“屏幕”、“选项卡”)但使用标准命名约定的类型的支持。

虽然viewSuffix参数是可选的,默认为“View”,但没有必要以这种方式调用此方法,因为定位器类已经为“View”和“Page”视图名称后缀添加了类型映射,尽管如果定位器类使用ConfigureTypeMappings()方法和修改TypeMappingConfiguration对象的ViewSuffixList属性进行了不同的配置,则情况可能并非如此。但是,修改配置对象的ViewSuffixList属性并重新配置locator类可以避免事后调用此方法。

请记住,如果配置对象的UseNameSuffixesInMappings属性设置为false,则此方法不会添加任何类型映射。在这种情况下,没有为其添加映射的默认类型命名约定。

代码语言:javascript
复制
//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.MainForm


ViewModelLocator.AddDefaultTypeMapping("Form");
//Resolves: MyProject.Views.MainForm -> MyProject.ViewModels.MainFormViewModel

ViewLocator.RegisterViewSuffix()

此方法用于向ViewLocator指示使用NameTransformer.AddRule()添加了支持自定义视图后缀的转换规则。调用AddNamespaceMapping()、AddTypeMapping()和AddDefaultTypeMapping()类型映射方法时,ViewLocator类会自动在内部调用此方法。

代码语言:javascript
复制
public static void RegisterViewSuffix(string viewSuffix)

viewSuffix参数是类型名称的后缀。应该是“视图”或“视图”的同义词。(可选)

为了使多视图支持正常工作,ViewLocator需要跟踪应用程序可能使用的所有视图后缀。尽管在使用新的类型映射方法添加名称转换规则时会自动管理此操作,但直接通过ViewLocator类的NameTransformer实例添加的转换规则将绕过此注册步骤。因此,在这种情况下需要调用ViewLocator.RegisterViewSuffix()。在添加新条目之前,该方法将对现有条目执行检查。

代码语言:javascript
复制
//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()

此方法用于在源命名空间和一个或多个目标命名空间之间添加类型映射。结果类型映射创建了一个转换规则,该规则支持标准类型命名约定,但具有自定义命名空间命名约定。或者,可以为此映射指定自定义视图后缀。

代码语言:javascript
复制
public static void AddNamespaceMapping(string nsSource, string[] nsTargets, string viewSuffix = "View")

nsSource:源类型的命名空间

nsTargets:作为数组的目标类型的名称空间

viewSuffix:类型名称的后缀。应该是“视图”或“视图”的同义词。(可选)

代码语言:javascript
复制
public static void AddNamespaceMapping(string nsSource, string nsTarget, string viewSuffix = "View")

nsSource:源类型的命名空间

nsTarget:目标类型的命名空间

viewSuffix:类型名称的后缀。应该是“视图”或“视图”的同义词。(可选)

此方法支持在nsSource参数中使用通配符(用*)。当nsSource参数使用空字符串(或string.Empty)时,作为nsTarget/nsTargets参数传递的命名空间将追加到源类型的命名空间。有关更多详细信息,请参阅示例。

可以将数组作为目标命名空间的参数传递,以指示目标类型可以存在于多个命名空间中(“一对多”映射)。由于定位器类被设计为拾取与名称转换规则匹配的类型的第一个匹配项,因此,如果某个类型实际上不存在于某个目标名称空间中,或者不同名称空间中存在多个共享同一名称的类型,则无所谓。此机制的一个可能用例是将ViewModel命名空间映射到自定义视图的程序集和标准视图的另一个程序集。如果自定义视图的部件不存在,或者自定义视图部件中不存在特定视图,则ViewLocator将从标准视图部件中拾取视图。

代码语言:javascript
复制
//"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.OrderHistoryView

ViewLocator.AddSubNamespaceMapping(),ViewModelLocator.AddSubNamespaceMapping()

此方法用于通过将给定的子名称空间替换为另一子名称空间,在源名称空间和一个或多个目标名称空间之间添加类型映射。结果类型映射创建了一个转换规则,该规则支持标准类型命名约定,但具有自定义命名空间命名约定。或者,可以为此映射指定自定义视图后缀。

代码语言:javascript
复制
public static void AddSubNamespaceMapping(string nsSource, string[] nsTargets, string viewSuffix = "View")

nsSource:源类型的子名称空间

nsTargets:目标类型为数组的子名称空间

viewSuffix:类型名称的后缀。应该是“视图”或“视图”的同义词。(可选)

代码语言:javascript
复制
public static void AddSubNamespaceMapping(string nsSource, string nsTarget, string viewSuffix = "View")

nsSource:源类型的子名称空间

nsTarget:目标类型的子名称空间

viewSuffix:类型名称的后缀。应该是“视图”或“视图”的同义词。(可选)

此方法支持在nsSource参数中使用通配符(用*)。当nsSource参数使用空字符串(或string.Empty)时,作为nsTarget/nsTargets参数传递的命名空间将追加到源类型的命名空间。当nsSource为空字符串或以通配符开头和结尾时,其行为与AddNamespaceMapping()的行为相同。与AddNamespaceMapping()一样,AddSubNamespaceMapping()方法支持一对多映射。有关说明,请参阅AddNamespaceMapping()的说明。

此方法在配置时为配置对象的ViewSuffixList中的每个视图后缀在内部调用。由DefaultSubNamespaceForViews和DefaultSubNamespaceForViewModels指定的子名称用于映射。如果不需要“视图”和“ViewModels”子名称空间之间的默认映射,则可以使用适当的配置设置来消除直接调用AddSubNamespaceMapping()的需要。

代码语言:javascript
复制
//Add support for Spanish namespaces
ViewLocator.AddSubNamespaceMapping("ModelosDeVistas", "Vistas");
//Resolves: MiProyecto.ModelosDeVistas.Clientes.ClienteViewModel -> MiProyecto.Vistas.Clientes.ClienteView
 
ViewModelLocator.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.CustomerView
 
ViewLocator.AddSubNamespaceMapping("ViewModels.*", "Views");
//Resolves: MyApp.ViewModels.Some.Name.Space.CustomerViewModel -> MyApp.Views.CustomerView
 
ViewLocator.AddSubNamespaceMapping("MyApp.*.ViewModels", "ExtLib.Views");
//Resolves: MyCompany.MyApp.SomeNamespace.ViewModels.CustomerViewModel -> MyCompany.ExtLib.Views.CustomerView

ViewLocator.AddTypeMapping(),ViewModelLocator.AddTypeMapping()

此方法用于添加表示为基于正则表达式的转换的类型映射。结果类型映射创建了一个转换规则,该规则支持标准类型命名约定,但具有自定义命名空间命名约定。或者,可以为此映射指定自定义视图后缀。

代码语言:javascript
复制
public static void AddTypeMapping(string nsSourceReplaceRegEx, string nsSourceFilterRegEx, string[] nsTargetsRegEx, string viewSuffix = "View")

nsSourceReplaceRegEx:源命名空间的RegEx替换模式

nsSourceFilterRegEx:源命名空间的正则表达式筛选器模式

nsTargetsRegEx:目标命名空间的RegEx替换值数组

viewSuffix:类型名称的后缀。应该是“视图”或“视图”的同义词。(可选)

代码语言:javascript
复制
public static void AddTypeMapping(string nsSourceReplaceRegEx, string nsSourceFilterRegEx, string nsTargetRegEx, string viewSuffix = "View")

nsSourceReplaceRegEx:源命名空间的RegEx替换模式

nsSourceFilterRegEx:源命名空间的正则表达式筛选器模式

nsTargetsRegEx:目标命名空间的RegEx替换值

viewSuffix:类型名称的后缀。应该是“视图”或“视图”的同义词。(可选)

有关创建基于正则表达式的转换规则的详细信息,请参阅NameTransformer上的文档。与通过NameTransformer类添加转换规则不同,此方法将命名空间转换与类型名转换分离。此外,它还支持一对多命名空间映射。有关说明,请参阅AddNamespaceMapping()的说明。

代码语言:javascript
复制
//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.TestView

最后

原文标题:Caliburn.Micro Xaml made easy

原文链接:https://caliburnmicro.com/documentation/custom-conventions

翻译:dotnet编程大全

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-12-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 dotNET编程大全 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Properties
  • ViewLocator.ConfigureTypeMapping(), ViewModelLocator.ConfigureTypeMapping() Methods
  • New Type Mapping Methods
    • ViewLocator.AddDefaultTypeMapping(), ViewModelLocator.AddDefaultTypeMapping()
    • 最后
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档