有没有办法避免使用Windows商店应用程序ResourceLoader使用硬编码的resw键?

有没有办法避免在Windows商店应用程序中使用resw文件中包含的全球化字符串使用硬编码键? 即

// 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#中的翻译 – 然后您知道所有密钥在编译时都是有效的,而不是运行时。 该模板生成以下代码:

 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模板生成的:

 <#@ 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)) { #> //------------------------------------------------------------------------------ //  // This code was generated by a resource generator. //  //------------------------------------------------------------------------------ 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 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; } #>