3

趣味のプロジェクト (WinRT アプリケーション) のクラス ライブラリにローカライズを追加しようとしています。リソース (.resw ファイル) の厳密に型指定されたクラスが生成されないことに驚いています。リソースからそのようなクラスを自動的に生成する T4 テンプレートまたはカスタム ツールはありますか?

私は簡単な T4 テンプレートを自分で作成しましたが、カスタム ソリューションにはいくつかの欠点があるため (たとえば、リソースへの変更を保存しても T4 変換がトリガーされないなど)、組み込みまたは MS 提供のメカニズムがあるかどうか疑問に思います。

4

4 に答える 4

3

これが私の元の解決策です(ただし、テキストテンプレートをサポートしていない可能性があるため、VS 2012 RC for Windows 8では機能しません)。テンプレートで設定することにより、正しいリソースファイルを指すようにテンプレートを構成する必要があります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スタイルのアプリケーションでは異なる名前空間を使用する必要があります。

于 2012-08-10T19:48:15.173 に答える
1

https://github.com/damieng/DamienGKit/tree/master/T4/ResourceGeneratorにRESWファイルから強力に生成されたリソースを提供するT4テンプレートがあります

ResourceGeneratorMetro.ttファイルとResourceGenerator.ttincludeファイルをプロジェクトにドロップし、ResourceGeneratorMetro.ttの6行目を変更して、生成するリソース名を含めます。

于 2012-11-26T22:51:36.460 に答える
1
System.IO.Path.GetDirectoryName(this.Host.TemplateFile) 

リソースファイルの相対ファイルパスを指定するだけで、T4テンプレートファイルの絶対パスを取得するのに役立ちます(ビジュアルスタジオ内で実行された場合のみ)。

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

私にとっては問題なく動作します

フォルダーに登りたい場合 ( ..// ここでは機能しません)、文字列を手動で編集して使用できます

于 2012-09-14T06:40:51.000 に答える