用于 Silverlight 应用程序的 T4 模板,用于生成在 .resx 文件中定义的文字字符串类






4.50/5 (8投票s)
一个用于 Silverlight 应用程序的 T4 模板,它生成一个包含 .resx 文件中定义的所有资源字符串的文字字符串类。它有助于使您的 Silverlight 代码更易于维护。
引言
本文介绍了如何使用简单的 T4 模板生成包含在 .resx 资源文件中定义的资源的文字字符串类。
背景
当将诸如 [Display] 或 [Required] 之类的 DataAnnotations 应用到您的业务实体以向属性添加元数据资源文本时,很容易出现类型错误,并且编译器无法帮助您定义问题。您只有在运行 Silverlight 应用程序时才会看到错误。
问题描述
我使用 VS2010 创建了一个默认的 Silverlight 业务应用程序,如下所示
在此项目中,有一个 User.shared.cs 文件,它添加了一些 DataAnnotations 以定义此实体的额外元数据。
代码如下所示
public sealed partial class RegistrationData
{
///
/// Gets and sets the user name.
///
[Key]
[Required(ErrorMessageResourceName = "ValidationErrorRequiredField",
ErrorMessageResourceType = typeof(ValidationErrorResources))]
[Display(Order = 0, Name = "UserNameLabel",
ResourceType = typeof(RegistrationDataResources))]
[RegularExpression("^[a-zA-Z0-9_]*$",
ErrorMessageResourceName = "ValidationErrorInvalidUserName",
ErrorMessageResourceType = typeof(ValidationErrorResources))]
[StringLength(255, MinimumLength = 4,
ErrorMessageResourceName = "ValidationErrorBadUserNameLength",
ErrorMessageResourceType = typeof(ValidationErrorResources))]
public string UserName { get; set; }
...
运行此 Silverlight 应用程序时,您会看到以下 注册 屏幕
如您所见,一切看起来都正确。
但是,如果您犯了类型错误(UserNameLabel_
而不是 UserNameLabel
)会发生什么?
项目编译正确,没有显示任何错误或警告。但是,运行应用程序时,注册 屏幕会出现一些错误
错误是
- UserName 显示在最后而不是最前面。
- UserName 不再正确翻译为“用户名”。
此问题的解决方案
我的解决方案是创建一个 T4 模板,它将读取 MyBusinessApplication.Web 项目中的 .resx 文件,并创建一个定义所有已定义字符串的类。
简单的 T4 模板如下所示
<#@ template debug="true" hostSpecific="true" #>
<#@ output extension=".cs" encoding="ASCII" #>
<#@ Assembly Name="System.Core.dll" #>
<#@ Assembly Name="System.Xml.dll" #>
<#@ Assembly Name="System.Xml.Linq.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Xml.Linq" #>
<#
string resourceFile = "RegistrationDataResources";
string PostFix = ""; // String / Label
#>
//------------------------------------------------------------------------------
// <auto-generated>
// This code was auto-generated at <#= DateTime.Now #>.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace MyBusinessApplication.Web.Resources
{
using System;
/// <summary>
/// A static helper class which exposes all strings as const
/// strings which are present in the resource file.
/// </summary>
[System.CodeDom.Compiler.GeneratedCodeAttribute(
"RegistrationDataResources.shared.tt", "1.0.0.0")]
public static class ResourceLiterals
{
<#
string filename = Path.Combine(Path.GetDirectoryName(this.Host.TemplateFile),
resourceFile + ".resx");
var names = (from e in XElement.Load(filename).Elements("data")
select e.Attribute("name").Value).ToList();
int idx = 0;
string name = names[0];
#>
/// <summary>
/// The string <#=name#>
/// </summary>
public const string <#=name#><#=PostFix#> = "<#=name#>";
<#
for (idx = 1 ; idx < names.Count(); idx++)
{
name = names[idx];
#>
/// <summary>
/// The string <#=name#>
/// </summary>
public const string <#=name#><#=PostFix#> = "<#=name#>";
<#
}
#>
}
}
创建一个名为 RegistrationDataResources.shared.t 的文件,并将其添加到解决方案中。将上面的内容复制到此 .tt 文件。
解决方案现在如下所示
现在可以更新 RegistrationData.cs 文件以使用静态类 'ResourceLiterals
'
public sealed partial class RegistrationData
{
/// <summary>
/// Gets and sets the user name.
/// </summary>
[Key]
[Required(ErrorMessageResourceName = "ValidationErrorRequiredField",
ErrorMessageResourceType = typeof(ValidationErrorResources))]
[Display(Order = 0, Name = ResourceLiterals.EmailLabel,
ResourceType = ResourceLiterals.ResourceType)] [RegularExpression("^[a-zA-Z0-9_]*$",
ErrorMessageResourceName = "ValidationErrorInvalidUserName",
ErrorMessageResourceType = typeof(ValidationErrorResources))]
[StringLength(255, MinimumLength = 4,
ErrorMessageResourceName = "ValidationErrorBadUserNameLength",
ErrorMessageResourceType = typeof(ValidationErrorResources))]
public string UserName { get; set; }
...
注意:文件名必须是 *.shared*,否则 Silverlight Presentation 项目将无法使用它。(RIA Services 将不会生成客户端代码。)
结论
现在您拥有强类型资源文字。将此 T4 模板作为起点并根据自己的需要进行调整。
可以在 此处 找到源代码。
历史
- 首次发布于 2010-08-17。