有没有一种方法可以避免在Windows应用商店ResourceLoader中使用硬编码的resw键? [英] Is there a way to avoid using hard-coded resw keys with the windows store app ResourceLoader?

查看:110
本文介绍了有没有一种方法可以避免在Windows应用商店ResourceLoader中使用硬编码的resw键?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有一种方法可以避免对Windows应用商店中resw文件中包含的全球化字符串使用硬编码键?即

Is there a way to avoid using hard-coded keys for the globalized strings contained in the resw file within a windows store app? i.e.

// I have to use a hard-coded string key, which may violate the
// DRY principle to gain access to the translation from C#:
var translation =
    Windows.ApplicationModel.Resources.ResourceLoader.GetString("MyStringKey/Text")

推荐答案

您可以使用下面的T4模板自动在resw文件周围生成C#包装器.这意味着您无需使用魔术字符串资源键来乱码,即可访问C#的翻译-这样,您就可以知道所有键在编译时(而不是运行时)都是有效的.该模板生成以下代码:

You can use the T4 template below to automatically generate a C# wrapper around your resw file. This means you have no need to litter your code with magic-string resource keys to access translations from C# - all your keys are then known to be valid at compile-time, rather than run-time. The template generates the following code:

internal static class Translation
{
    public static ResourceLoader ResourceLoader { get; private set; }

    static Translation()
    {
        ResourceLoader = new ResourceLoader();
    }

    public static string MyFirstString
    {
        get { return ResourceLoader.GetString("MyFirstString/Text"); }
    }
}

这是由以下T4模板生成的:

This is generated by the following T4 template:

<#@ 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 = @"en-GB\Resources.resw";
    var provider = new CSharpCodeProvider();
    string className = CreateClassName(provider);

    SetCurrentDirectory();
    if (File.Exists(inputFilePath)) {
#>
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a resource generator.
// </auto-generated>
//------------------------------------------------------------------------------
using Windows.ApplicationModel.Resources;

namespace <#= GetNamespace() #> {
    internal static class <#= className #> {
        public static ResourceLoader ResourceLoader { get; private set; }

        static <#= className #>() {
            ResourceLoader = new ResourceLoader();
        }
<#
        foreach (string name in GetResourceKeys(inputFilePath)) {
#>
        public static string <#= provider.CreateEscapedIdentifier(name.Replace(".Text", String.Empty).Replace(".Content", String.Empty).Replace(".FlowDirection", string.Empty)) #> {
            get { return ResourceLoader.GetString("<#= name.Replace(".Text", "/Text").Replace(".Content", "/Content").Replace(".FlowDirection", "/FlowDirection") #>"); }
        }
<#
        }
#>
    }
}
<#
    } 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 static IEnumerable<string> GetResourceKeys(string filePath) {
        XDocument doc = XDocument.Load(filePath);
        var rootElement = doc.Root.Elements().SingleOrDefault(x => x.Name == "root");
        if (rootElement == null)
        {
            throw new InvalidOperationException("No root element was found");
        }
        var dataElements = rootElement.Elements("data").ToList();
        var resourceKeys = dataElements.Select(e => e.Attribute("name").Value).ToList();
        return resourceKeys;
    }
#>

这篇关于有没有一种方法可以避免在Windows应用商店ResourceLoader中使用硬编码的resw键?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆