<#@ template debug="true" hostspecific="true" language="C#" #> <#@ assembly name="System.Core" #> <#@ assembly name="System.Windows.Forms" #> <#@ assembly name="Microsoft.VisualStudio.Shell.Interop.8.0" #> <#@ assembly name="EnvDTE" #> <#@ assembly name="EnvDTE80" #> <#@ import namespace="System" #> <#@ import namespace="System.Collections" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="System.IO" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Resources" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Text.RegularExpressions" #> <#@ import namespace="Microsoft.VisualStudio.Shell.Interop" #> <#@ import namespace="EnvDTE" #> <#@ import namespace="EnvDTE80" #> <# var hostServiceProvider = (IServiceProvider)Host; var dte = (EnvDTE.DTE)hostServiceProvider.GetService(typeof(EnvDTE.DTE)); var templateProjectItem = dte.Solution.FindProjectItem(Host.TemplateFile); var projectDirectory = Path.GetDirectoryName(templateProjectItem.ContainingProject.FullName); var ttDirectory = Path.Combine(projectDirectory, "Properties"); var projectName = Path.GetFileName(projectDirectory.TrimEnd('/')); var namedParameterMatcher = new Regex(@"\{([a-z]\w+)\}", RegexOptions.IgnoreCase); var numberParameterMatcher = new Regex(@"\{(\d+)\}"); foreach (var resxFile in Directory.EnumerateFiles(projectDirectory, "*.resx", SearchOption.AllDirectories)) { var fileName = Path.GetFileNameWithoutExtension(resxFile); var resourceStrings = new List(); using (var resxReader = new ResXResourceReader(resxFile)) { resxReader.UseResXDataNodes = true; foreach (DictionaryEntry entry in resxReader) { var node = (ResXDataNode)entry.Value; var value = (string)node.GetValue((System.ComponentModel.Design.ITypeResolutionService)null); bool usingNamedArgs = true; var match = namedParameterMatcher.Matches(value); if (match.Count == 0) { usingNamedArgs = false; match = numberParameterMatcher.Matches(value); } var arguments = match.Cast() .Select(m => m.Groups[1].Value) .Distinct(); if (!usingNamedArgs) { arguments = arguments.OrderBy(Convert.ToInt32); } resourceStrings.Add( new ResourceData { Name = node.Name, Value = value, Arguments = arguments.ToList(), UsingNamedArgs = usingNamedArgs }); } } GenerationEnvironment.AppendFormat( @"// namespace {0} {{ using System.Globalization; using System.Reflection; using System.Resources; internal static class {1} {{ private static readonly ResourceManager _resourceManager = new ResourceManager(""{0}.{1}"", typeof({1}).GetTypeInfo().Assembly); ", projectName, fileName); foreach (var resourceString in resourceStrings) { GenerationEnvironment.AppendLine(); RenderHeader(GenerationEnvironment, resourceString); RenderProperty(GenerationEnvironment, resourceString); GenerationEnvironment.AppendLine(); RenderHeader(GenerationEnvironment, resourceString); RenderFormatMethod(GenerationEnvironment, resourceString); } GenerationEnvironment.Append(@" private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); System.Diagnostics.Debug.Assert(value != null); if (formatterNames != null) { for (var i = 0; i < formatterNames.Length; i++) { value = value.Replace(""{"" + formatterNames[i] + ""}"", ""{"" + i + ""}""); } } return value; } } } "); var outputPath = Path.Combine(ttDirectory, fileName + ".Designer.cs"); File.WriteAllText(outputPath, GenerationEnvironment.ToString()); GenerationEnvironment.Length = 0; } #> <#+ private static void RenderHeader(StringBuilder builder, ResourceData resourceString) { builder.Append(" /// ") .AppendLine(); foreach (var line in resourceString.Value.Split(new[] { Environment.NewLine }, StringSplitOptions.None)) { builder.AppendFormat(" /// {0}", line.Replace("<", "<").Replace(">", ">")) .AppendLine(); } builder.Append(" /// ") .AppendLine(); } private static void RenderProperty(StringBuilder builder, ResourceData resourceString) { builder.AppendFormat(" internal static string {0}", resourceString.Name) .AppendLine() .AppendLine(" {") .AppendFormat(@" get {{ return GetString(""{0}""); }}", resourceString.Name) .AppendLine() .AppendLine(" }"); } private static void RenderFormatMethod(StringBuilder builder, ResourceData resourceString) { builder.AppendFormat(" internal static string Format{0}({1})", resourceString.Name, resourceString.Parameters) .AppendLine() .AppendLine(" {"); if(resourceString.Arguments.Count > 0) { builder.AppendFormat(@" return string.Format(CultureInfo.CurrentCulture, GetString(""{0}""{1}), {2});", resourceString.Name, resourceString.UsingNamedArgs ? ", " + resourceString.FormatArguments : null, resourceString.ArgumentNames); } else { builder.AppendFormat(@" return GetString(""{0}"");", resourceString.Name); } builder.AppendLine() .AppendLine(" }"); } private class ResourceData { public string Name { get; set; } public string Value { get; set; } public List Arguments { get; set; } public bool UsingNamedArgs { get; set; } public string FormatArguments { get { return string.Join(", ", Arguments.Select(a => "\"" + a + "\"")); } } public string ArgumentNames { get { return string.Join(", ", Arguments.Select(GetArgName)); } } public string Parameters { get { return string.Join(", ", Arguments.Select(a => "object " + GetArgName(a))); } } public string GetArgName(string name) { return UsingNamedArgs ? name : 'p' + name; } } #>