使用名称Transformer


NameTransformer是在Caliburn.Micro v1.1中引入的,它是ViewLocator和ViewModelLocator如何将类名映射到其伙伴角色的一个组成部分。虽然您可以覆盖这些服务上的各种函数来替换底层行为,但您的大多数需求都应该通过使用适当的NameTransformer配置规则来满足,NameTransformer描述了您独特的映射策略。


名称转换基于使用正则表达式模式匹配的规则。执行转换时,将按顺序计算所有已注册的规则。默认情况下,NameTransformer返回所有匹配规则生成的结果名称。ViewLocator和ViewModelLocator类将使用结果名称列表按顺序检查AssemblySource.Instance集合中是否存在匹配类型。找到类型后,将忽略列表中的其余名称。尽管定位器类将始终最多返回一种类型,而不管NameTransformer返回的名称数量如何,但能够指定NameTransformer如何构造名称列表以更好地控制将定位的类型是很重要的。控制的主要手段是通过顺序。由于定位器类需要支持一些现成的类型命名约定,因此会自动添加一些默认名称转换规则。但是,为了能够支持自定义规则并允许它们优先于默认规则,NameTransformer按照与添加规则相反的顺序(LIFO)对规则进行求值。通常,您希望在更具体的规则之后评估更一般的规则。因此,在向NameTransformer添加规则时,必须首先添加更一般的规则,最后添加更具体的规则。要将NameTransformer返回的名称限制为第一个匹配规则生成的名称,可以将NameTransformer上的UseGuardRuleSelection属性设置为false。默认情况下,UseGuardRuleSelection设置为true。


自定义规则是通过调用ViewLocator和ViewModelLocator类维护的NameTransformer对象的AddRule()方法添加的。两个类都引用各自的NameTransformer静态实例,因此每个类都维护自己的一组规则。


呼叫约定如下:



public void AddRule(string replacePattern, IEnumerable<string> replaceValueList, string globalFilterPattern = null)

replacePattern:用于替换全部或部分输入字符串的正则表达式模式


replaceValueList:应用于replacePattern的字符串集合


globalFilterPattern:用于确定是否应计算规则的正则表达式模式。可选择的



public void AddRule(string replacePattern, string replaceValue, string globalFilterPattern = null)

replacePattern:用于替换全部或部分输入字符串的正则表达式模式


replaceValue:应用于replacePattern的字符串


globalFilterPattern:用于确定是否应计算规则的正则表达式模式。可选择的


为了说明如何使用此方法,我们可以查看ViewLocator类添加的一个内置规则:



NameTransformer.AddRule("Model$", string.Empty);

此转换规则查找终止ViewModel名称的子字符串“Model”,并去掉该子字符串(即替换为string.Empty或“null string”)。第一个参数中的“$”表示模式必须在源字符串的末尾匹配。如果“模型”存在于其他任何地方,则模式不匹配。由于此调用未包含可选的“globalFilterPattern”参数,因此此规则适用于所有ViewModel名称。


此规则产生以下结果:

C# WPF MVVM开发框架Caliburn.Micro 名称Transformer⑩①_字符串

ViewModelLocator添加的相应内置规则为:



NameTransformer.AddRule(@"(?<fullname>^.*$)", @"${fullname}Model");

这个规则接受任何输入,并在末尾添加“Model”。此规则使用正则表达式捕获组,这在复杂转换中非常有用。“replacePattern”将视图的全名分配给名为“fullname”的捕获组,“replaceValue”将其转换为“Model”。


为了演示“globalFilterPattern”是如何应用的,我们可以看看ViewModelLocator的另外两个内置规则:

//Check for <Namespace>.<BaseName>View construct
NameTransformer.AddRule
(
@"(?<namespace>(.*\.)*)(?<basename>[A-Za-z_]\w*)(?<suffix>View$)",
new[] {
@"${namespace}${basename}ViewModel",
@"${namespace}${basename}",
@"${namespace}I${basename}ViewModel",
@"${namespace}I${basename}"
},
@"(.*\.)*[A-Za-z_]\w*View$"
);
//Check for <Namespace>.Views.<BaseName>View construct
NameTransformer.AddRule
(
@"(?<namespace>(.*\.)*)Views\.(?<basename>[A-Za-z_]\w*)(?<suffix>View$)",
new[] {
@"${namespace}ViewModels.${basename}ViewModel",
@"${namespace}ViewModels.${basename}",
@"${namespace}ViewModels.I${basename}ViewModel",
@"${namespace}ViewModels.I${basename}"
},
@"(.*\.)*Views\.[A-Za-z_]\w*View$"
);

这两个调用的“globalFilterPattern”参数相同,只是在第二个方法调用的参数中添加了“Views.”。这表示仅当名称空间名称以“视图”(包括点)结尾时,才应应用该规则。如果模式匹配,则结果是ViewModel名称的数组,其命名空间以“ViewModels”结尾。


第一条规则回显原始名称空间不变,将涵盖所有其他情况。如前所述,首先添加最不特定的规则。它涵盖了当名称空间不以“视图”结尾时的失败情况。


添加自定义的特定于应用程序的转换规则时,下面的替换模式应该非常有用。替换模式采用完全限定的ViewModel名称,并将其分成捕获组,这些捕获组应涵盖几乎所有转换:



(?<nsfull>((?<nsroot>[A-Za-z_]\w*\.)(?<nsstem>([A-Za-z_]\w*\.)*))?(?<nsleaf>[A-Za-z_]\w*\.))?(?<basename>[A-Za-z_]\w*)(?<suffix>ViewModel$)

例如,添加以下规则:




ViewLocator.NameTransformer.AddRule
(
@"(?<nsfull>((?<nsroot>[A-Za-z_]\w*\.)(?<nsstem>([A-Za-z_]\w*\.)*))?(?<nsleaf>[A-Za-z_]\w*\.))?(?<basename>[A-Za-z_]\w*)(?<suffix>ViewModel$)",
@"nsfull=${nsfull}, nsroot=${nsroot}, nsstem=${nsstem}, nsleaf=${nsleaf}, basename=${basename}, suffix=${suffix}"
);

将产生以下结果:

C# WPF MVVM开发框架Caliburn.Micro 名称Transformer⑩①_名称空间_02

笔记:


通过将“ViewModel$”更改为“View$”,上述相同的替换模式可用于ViewModelLocator。


您永远不会像上面的例子那样构造replace值,因为它会产生非法的类型名。它只是一个replace值,它将回显所有捕获组以供演示。


您可能会注意到,捕获组并不是相互排斥的。捕获组可以如示例中所示进行嵌套,以便“nsfull”捕获完整名称空间,“nsroot”、“nsstem”和“nsleaf”捕获该名称空间的各个组件。如果需要“交换”任何一个单独的组件,则可以使用单独的组件。


上面示例中的捕获组“后缀”对以“ViewModels”结尾的名称进行模式匹配。此捕获组的主要目的不是将其用作转换的一部分,因为ViewLocator的目的是解析视图名称。使用此捕获组的主要原因是防止子字符串“ViewModels”在“basename”组中被捕获,在大多数情况下,这是字符串转换的一部分。


02

最后

 

翻译:dotnet编程大全