use namespace="System" use namespace="System.Collections.Generic" use namespace="System.IO" use namespace="System.Linq" use namespace="System.Text" use namespace="System.Xml.Linq" default resxFile='' @{ var projectDir = Path.GetDirectoryName(resxFile); var outDirectory = Path.Combine(projectDir, "Properties"); var projectName = Path.GetFileName(projectDir.TrimEnd((char)'/')); var namedParameterMatcher = new Regex(@"\{([a-z]\w+)\}", RegexOptions.IgnoreCase); var numberParameterMatcher = new Regex(@"\{(\d+)\}"); var generatingEnvironment = new StringBuilder(); var fileName = Path.GetFileNameWithoutExtension(resxFile); var resourceStrings = new List(); var xml = XDocument.Load(resxFile); foreach (var entry in xml.Descendants("data")) { var name = entry.Attribute("name").Value; var value = entry.Element("value").Value; 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 = name, Value = value, Arguments = arguments.ToList(), UsingNamedArgs = usingNamedArgs }); } generatingEnvironment.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) { generatingEnvironment.AppendLine(); RenderHeader(generatingEnvironment, resourceString); RenderProperty(generatingEnvironment, resourceString); generatingEnvironment.AppendLine(); RenderHeader(generatingEnvironment, resourceString); RenderFormatMethod(generatingEnvironment, resourceString); } generatingEnvironment.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; } } } "); Directory.CreateDirectory(outDirectory); var outputPath = Path.Combine(outDirectory, fileName + ".Designer.cs"); File.WriteAllText(outputPath, generatingEnvironment.ToString()); } functions @{ private static void RenderHeader(StringBuilder builder, ResourceData resourceString) { builder.Append(" /// ") .AppendLine(); foreach (var line in resourceString.Value.Split(new[] { '\n' }, StringSplitOptions.None)) { builder.AppendFormat(" /// {0}", new XText(line)) .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; } } }