Click here to Skip to main content
15,897,226 members
Articles / Desktop Programming / WPF

StringsResourceGenerator, Custom Task + Add-in for managing strings in ResourceDictionary from code

Rate me:
Please Sign up or sign in to vote.
4.05/5 (8 votes)
27 May 2008CPOL4 min read 28.5K   291   10  
Creates a XAML file for your strings and generates a class to simplify use from code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Build.Utilities;
using System.Xml.Linq;
using System.IO;
using System.Collections.ObjectModel;
using Microsoft.Build.Framework;

namespace StringsResourceGeneratorTask
{
    public class StringsResourceGeneratorTask : Task
    {
        #region Constructors

        public StringsResourceGeneratorTask()
        {
        }

        #endregion

        #region Properties

        [Required]
        public string StringsResourceFileName { get; set; }

        public string AssemblyName { get; set; }

        public string Namespace { get; set; }

        public string ClassName { get; set; }

        internal CodeTypeController CodeTypeController { get; set; }

        protected XElement XamlDocument { get; set; }

        protected IEnumerable<string> StringProperties { get; set; }

        #endregion

        #region Public Functions

        public override bool Execute()
        {
            if (StringsResourceFileName == null || StringsResourceFileName == string.Empty)
            {
                Log.LogMessage(Microsoft.Build.Framework.MessageImportance.Normal, Resources.StringsResourceNotFound, null);
                return false;
            }

            string directoryResources = Path.GetDirectoryName(this.StringsResourceFileName);
            string fileName = Path.GetFileNameWithoutExtension(this.StringsResourceFileName);
            string directoryProject = Path.GetDirectoryName(this.BuildEngine.ProjectFileOfTaskNode);

            string xamlFileName = Path.Combine(directoryProject, Path.Combine(directoryResources, fileName + ".xaml"));

            CodeType codeType = CodeTypeController.GetCodeTypeFromXamlFile(xamlFileName);

            try
            {
                this.CodeTypeController = CodeTypeController.GetController(codeType);
            }
            catch (Exception e)
            {
                Log.LogMessage(Microsoft.Build.Framework.MessageImportance.Normal, Resources.CodeTypeControllerNotFound, null);
                Log.LogMessage(Microsoft.Build.Framework.MessageImportance.High, e.Message, null);
                return false;
            }

            if (!ReadXamlDocument(xamlFileName))
                return false;

            string projectName = Path.GetFileNameWithoutExtension(this.BuildEngine.ProjectFileOfTaskNode);
            if (!UpdateCodeDocument(CodeTypeController.CodeFileName, projectName, projectName + "." + directoryResources, this.StringProperties))
                return false;

            return true;
        }

        #endregion

        #region Private Functions

        bool ReadXamlDocument(string xamlFileName)
        {
            try
            {
                XamlDocument = XElement.Load(xamlFileName);
            }
            catch (Exception e)
            {
                Log.LogMessage(Microsoft.Build.Framework.MessageImportance.High, Resources.StringsFileNameNotFound, null);
                Log.LogMessage(Microsoft.Build.Framework.MessageImportance.High, e.Message, null);
                
                return false;
            }

            IEnumerable<ResourceProperty> resourceProperties = null;
            try
            {
                XNamespace xmlnsSystem = XamlDocument.GetNamespaceOfPrefix("system");
                XNamespace xmlnsX = XamlDocument.GetNamespaceOfPrefix("x");

                IEnumerable<XElement> xamlStrings = XamlDocument.Elements(xmlnsSystem + "String");

                resourceProperties = GetResourceProperties(xmlnsX, xamlStrings);
            }
            catch (Exception e)
            {
                Log.LogMessage(Microsoft.Build.Framework.MessageImportance.High, Resources.XamlReadingError, null);
                Log.LogMessage(Microsoft.Build.Framework.MessageImportance.High, e.Message, null);
                
                return false;
            }

            try
            {
                this.StringProperties = GetPropertyCodes(resourceProperties);
            }
            catch (Exception e)
            {
                Log.LogMessage(Microsoft.Build.Framework.MessageImportance.High, e.Message, null);

                return false;
            }

            return true;
        }

        bool UpdateCodeDocument(string codeFileName, string projectName, string namespaceName, IEnumerable<string> stringProperties)
        {
            string codeText = this.CodeTypeController.StringsCodeTemplate;

            string properties = string.Empty;
            foreach (string stringProperty in stringProperties)
            {
                properties +=
                    System.Environment.NewLine +
                    stringProperty +
                    System.Environment.NewLine;
            }

            codeText = codeText.Replace("$(STRINGRESOURCEFILENAME)", this.StringsResourceFileName);
            codeText = codeText.Replace("$(PROPERTIES)", properties);

            if (this.ClassName == null || this.ClassName == string.Empty)
                codeText = codeText.Replace("$(CLASSNAME)", "Strings");
            else
                codeText = codeText.Replace("$(CLASSNAME)", this.ClassName);

            if (this.Namespace == null || this.Namespace == string.Empty)
                codeText = codeText.Replace("$(NAMESPACE)", namespaceName);
            else
                codeText = codeText.Replace("$(NAMESPACE)", this.Namespace);

            if (this.AssemblyName == null || this.AssemblyName == string.Empty)
                codeText = codeText.Replace("$(ASSEMBLY)", projectName);
            else
                codeText = codeText.Replace("$(ASSEMBLY)", this.AssemblyName);

            File.WriteAllText(codeFileName, codeText);

            return true;
        }

        IEnumerable<ResourceProperty> GetResourceProperties(XNamespace xmlns, IEnumerable<XElement> xamlStrings)
        {            
            IEnumerable<ResourceProperty> resourceProperties =
                from xamlString in xamlStrings
                select new ResourceProperty()
                {
                    Key = xamlString.Attribute(xmlns + "Key").Value,
                    Content = xamlString.Value
                };

            return resourceProperties;
        }

        IEnumerable<string> GetPropertyCodes(IEnumerable<ResourceProperty> resourceProperties)
        {
            Collection<string> propertyCodes = new Collection<string>();

            foreach (ResourceProperty resourceProperty in resourceProperties)
            {
                string propertyCode = this.CodeTypeController.GeneratePropertyCode(resourceProperty);
                propertyCodes.Add(propertyCode);
            }

            return propertyCodes;
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Italy Italy
I am a biomedical engineer. I work in Genoa as software developer. I developed MFC ActiveX controls for industrial automation for 2 years and packages for Visual Studio 2005 for 1 year. Currently I'm working in .NET 3.5 in biomedical area.

Comments and Discussions