是否有任何T4模板或自定义工具从.resw文件生成类?

时间:2012-08-08 20:39:37

标签: c# localization windows-8 microsoft-metro windows-runtime

我正在尝试在我的爱好项目(WinRT应用程序)中向本地库添加本地化。我很惊讶它没有为资源生成强类型类(.resw文件)。是否有任何T4模板或自定义工具自动从资源生成此类?

我自己编写了简单的T4模板,但我想知道是否有任何内置或MS提供的机制,因为自定义解决方案有一些缺点(例如保存对资源的更改不会触发T4转换)。

4 个答案:

答案 0 :(得分:3)

这是我的原始解决方案(但它在Windows 2012的VS 2012 RC中不起作用,因为它probably doesn't support Text templating)。您只需在模板中设置inputFilePath即可将模板配置为指向正确的资源文件。

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="System.Xml.Linq" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Xml.Linq" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="Microsoft.CSharp" #>
<#@ import namespace="EnvDTE" #>
<#@ output extension=".cs" #>
<#
    DTE env = GetVSEnvironment();
    var inputFilePath = @"Resources\Strings\en\Resources.resw";
    var provider = new CSharpCodeProvider();
    string className = CreateClassName(provider);

    SetCurrentDirectory();
    if (File.Exists(inputFilePath)) {
#>
using Windows.ApplicationModel.Resources;

namespace <#= GetNamespace() #> {
    public static class <#= className #> {
        private static ResourceLoader _resourceLoader;

        static <#= className #>() {
            _resourceLoader = new ResourceLoader("<#= GetResourcePath(env) #>");
        }
<#
        foreach (string name in GetResourceKeys(inputFilePath)) {
#>
        public static string <#= provider.CreateEscapedIdentifier(name) #> {
            get { return _resourceLoader.GetString("<#= name #>"); }
        }
<#
        }
#>
    }
}
<#
    } else {
        throw new FileNotFoundException(String.Format("Unable to find Resource file: {0}", inputFilePath)); 
    } 
#>
<#+
    private DTE GetVSEnvironment() {
        DTE env = null;
        var provider = Host as IServiceProvider;
        if (provider != null) {
            env = provider.GetService(typeof(DTE)) as DTE;
        }

        if (env == null) {
            throw new InvalidOperationException("Template must be executed from Visual Studio");
        }

        return env;
    }

    private void SetCurrentDirectory() {
        Directory.SetCurrentDirectory(Host.ResolvePath(""));
    }

    private string CreateClassName(CSharpCodeProvider provider) {
        string name = Path.GetFileNameWithoutExtension(Host.TemplateFile);
        return provider.CreateEscapedIdentifier(name);
    }

    private string GetNamespace() {
        return Host.ResolveParameterValue("directiveId", "namespaceDirectiveProcessor", "namespaceHint");
    }

    private string GetResourcePath(DTE env) {
        Project project = env.Solution.FindProjectItem(Host.TemplateFile).ContainingProject;
        string assemblyName = project.Properties.Item("AssemblyName").Value.ToString();
        return assemblyName + "/Resources";
    }

    private static IEnumerable<string> GetResourceKeys(string filePath) {
        XDocument doc = XDocument.Load(filePath);
        return doc.Root.Elements("data").Select(e => e.Attribute("name").Value);
    }
#>

我认为我将通过用于.resx文件的普通自定义工具解决问题,但Metro风格应用程序需要使用不同的命名空间。

答案 1 :(得分:1)

System.IO.Path.GetDirectoryName(this.Host.TemplateFile) 

可以帮助您获取绝对T4模板文件路径(仅在visual studio中执行时),然后只需提供资源文件的相对文件路径。

var inputFilePath =System.IO.Path.GetDirectoryName(this.Host.TemplateFile) 
+ "\\Resources\\Strings\\en\\Resources.resw" ;

对我有用

如果你想爬到文件夹(..//在这里不起作用)你可以手动编辑字符串并使用它

答案 2 :(得分:1)

我刚刚在CodePlex上启动了名为ResW File Code Generator的Visual Studio 2012自定义工具项目

答案 3 :(得分:1)

我有一个T4模板,可以在https://github.com/damieng/DamienGKit/tree/master/T4/ResourceGenerator

的RESW文件中提供强大的生成资源

只需删除项目中的ResourceGeneratorMetro.tt和ResourceGenerator.ttinclude文件,然后修改ResourceGeneratorMetro.tt的第6行,以包含您希望它生成的资源名称。