65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (8投票s)

2010年8月17日

CPOL

2分钟阅读

viewsIcon

26955

downloadIcon

75

一个用于 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。
© . All rights reserved.