using System; using System.CodeDom; using System.CodeDom.Compiler; using System.Globalization; using System.IO; using System.Text; using Microsoft.CSharp; namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool { public class CodeDomCodeGenerator : CodeGenerator { private readonly string className; private readonly CodeNamespace codeNamespace; private readonly CodeCompileUnit compileUnit; private readonly CodeDomProvider provider; public CodeDomCodeGenerator(IResourceParser resourceParser, string className, string defaultNamespace, CodeDomProvider codeDomProvider = null) : base(resourceParser, defaultNamespace) { this.className = className; compileUnit = new CodeCompileUnit(); provider = codeDomProvider ?? new CSharpCodeProvider(); codeNamespace = new CodeNamespace(defaultNamespace); } public override string GenerateCode() { codeNamespace.Comments.Add(new CodeCommentStatement("--------------------------------------------------------------------------------------------------")); codeNamespace.Comments.Add(new CodeCommentStatement("")); codeNamespace.Comments.Add(new CodeCommentStatement("\tThis code was generated by ResW File Code Generator (http://reswcodegen.codeplex.com)")); codeNamespace.Comments.Add(new CodeCommentStatement("\tResW File Code Generator was written by Christian Resma Helle")); codeNamespace.Comments.Add(new CodeCommentStatement("\tand is under GNU General Public License version 2 (GPLv2)")); codeNamespace.Comments.Add(new CodeCommentStatement(string.Empty)); codeNamespace.Comments.Add(new CodeCommentStatement("\tThis code contains a helper class exposing property representations")); codeNamespace.Comments.Add(new CodeCommentStatement("\tof the string resources defined in the specified .ResW file")); codeNamespace.Comments.Add(new CodeCommentStatement(string.Empty)); codeNamespace.Comments.Add(new CodeCommentStatement("\tGenerated: " + DateTime.Now.ToString(CultureInfo.InvariantCulture))); codeNamespace.Comments.Add(new CodeCommentStatement("")); codeNamespace.Comments.Add(new CodeCommentStatement("--------------------------------------------------------------------------------------------------")); codeNamespace.Imports.Add(new CodeNamespaceImport("Windows.ApplicationModel.Resources")); var targetClass = new CodeTypeDeclaration(className) { IsClass = true, IsPartial = true, Attributes = MemberAttributes.Public | MemberAttributes.Static }; const string resourceLoaderType = "ResourceLoader"; var resourceLoaderField = new CodeMemberField(resourceLoaderType, "resourceLoader") { Attributes = MemberAttributes.Private | MemberAttributes.Static | MemberAttributes.Final }; targetClass.Members.Add(resourceLoaderField); var constructor = new CodeTypeConstructor(); var executingAssemblyVar = new CodeVariableDeclarationStatement(typeof(string), "executingAssemblyName"); var executingAssemblyInit = new CodeAssignStatement( new CodeVariableReferenceExpression("executingAssemblyName"), new CodeSnippetExpression("Windows.UI.Xaml.Application.Current.GetType().AssemblyQualifiedName")); var executingAssemblySplit = new CodeVariableDeclarationStatement(typeof(string[]), "executingAssemblySplit"); var executingAssemblyInit2 = new CodeAssignStatement( new CodeVariableReferenceExpression("executingAssemblySplit"), new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("executingAssemblyName"), "Split", new CodePrimitiveExpression(','))); var executingAssemblyInit3 = new CodeAssignStatement( new CodeVariableReferenceExpression("executingAssemblyName"), new CodeArrayIndexerExpression(new CodeVariableReferenceExpression("executingAssemblySplit"), new CodePrimitiveExpression(1))); var currentAssemblyVar = new CodeVariableDeclarationStatement(typeof(string), "currentAssemblyName"); var currentAssemblyInit = new CodeAssignStatement( new CodeVariableReferenceExpression("currentAssemblyName"), new CodePropertyReferenceExpression(new CodeTypeOfExpression(className), "AssemblyQualifiedName")); var currentAssemblySplit = new CodeVariableDeclarationStatement(typeof(string[]), "currentAssemblySplit"); var currentAssemblyInit2 = new CodeAssignStatement( new CodeVariableReferenceExpression("currentAssemblySplit"), new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("currentAssemblyName"), "Split", new CodePrimitiveExpression(','))); var currentAssemblyInit3 = new CodeAssignStatement( new CodeVariableReferenceExpression("currentAssemblyName"), new CodeArrayIndexerExpression(new CodeVariableReferenceExpression("currentAssemblySplit"), new CodePrimitiveExpression(1))); var createResourceLoader = new CodeConditionStatement( new CodeSnippetExpression("executingAssemblyName.Equals(currentAssemblyName)"), new CodeStatement[] // true { new CodeAssignStatement( new CodeFieldReferenceExpression(null, "resourceLoader"), new CodeObjectCreateExpression(new CodeTypeReference("ResourceLoader"), new CodeSnippetExpression("\"" + className + "\""))) }, new CodeStatement[] // false { new CodeAssignStatement( new CodeFieldReferenceExpression(null, "resourceLoader"), new CodeObjectCreateExpression(new CodeTypeReference("ResourceLoader"), new CodeSnippetExpression("currentAssemblyName + \"/" + className + "\""))) }); constructor.Statements.Add(executingAssemblyVar); constructor.Statements.Add(executingAssemblyInit); constructor.Statements.Add(executingAssemblySplit); constructor.Statements.Add(executingAssemblyInit2); constructor.Statements.Add(executingAssemblyInit3); constructor.Statements.Add(currentAssemblyVar); constructor.Statements.Add(currentAssemblyInit); constructor.Statements.Add(currentAssemblySplit); constructor.Statements.Add(currentAssemblyInit2); constructor.Statements.Add(currentAssemblyInit3); constructor.Statements.Add(createResourceLoader); targetClass.Members.Add(constructor); var resources = ResourceParser.Parse(); foreach (var item in resources) { if (string.IsNullOrEmpty(item.Name) || item.Name.Contains(".")) continue; var property = new CodeMemberProperty { Name = item.Name.Trim(), Attributes = MemberAttributes.Public | MemberAttributes.Static, HasGet = true, Type = new CodeTypeReference(typeof(string)) }; property.Comments.Add(new CodeCommentStatement("", true)); property.Comments.Add(new CodeCommentStatement("Localized resource similar to \"" + (item.Value ?? item.Name) + "\"", true)); property.Comments.Add(new CodeCommentStatement("", true)); property.GetStatements.Add( new CodeMethodReturnStatement( new CodeMethodInvokeExpression( new CodeFieldReferenceExpression(null, "resourceLoader"), "GetString", new CodePrimitiveExpression(item.Name)))); targetClass.Members.Add(property); } codeNamespace.Types.Add(targetClass); compileUnit.Namespaces.Add(codeNamespace); return GenerateCodeFromCompileUnit(); } private string GenerateCodeFromCompileUnit() { var options = new CodeGeneratorOptions { BracingStyle = "C" }; var code = new StringBuilder(); using (var writer = new StringWriter(code)) provider.GenerateCodeFromCompileUnit(compileUnit, writer, options); return code.ToString(); } } }