Click here to Skip to main content
15,881,424 members
Articles / Programming Languages / C#

A Flexible Plugin System

Rate me:
Please Sign up or sign in to vote.
4.98/5 (25 votes)
3 Sep 2008LGPL34 min read 130.5K   1.8K   163  
A generic plugin system used to load and manage plugins
using System;
using System.Collections.Generic;

namespace Fadd.Globalization
{
    /// <summary>
    /// Contains language translations used to create multilingual applications
    /// </summary>
    /// <remarks>
    /// The LanguageNode provides a base class for different implementations of a hierachial language structure
    /// </remarks>
    public abstract class LanguageNode
    {
        /// <summary>
        /// An empty language node (used instead of null).
        /// </summary>
        public static EmptyLanguageNode Empty = new EmptyLanguageNode(0);

        private int _defaultLCID;
        private string _name = string.Empty;
        private readonly Dictionary<string, LanguageNode> _subNodes = new Dictionary<string, LanguageNode>();
        private LanguageNode _parentNode;

        /// <summary>
        /// Parent language category
        /// </summary>
        public LanguageNode ParentNode
        {
            get { return _parentNode; }
            internal set { _parentNode = value; }
        }

        /// <summary>
        /// All sub categories
        /// </summary>
        public Dictionary<string, LanguageNode> SubNodes
        {
            get { return _subNodes; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="LanguageNode"/> class.
        /// </summary>
        /// <param name="defaultLCID">The default LCID.</param>
        protected LanguageNode(int defaultLCID)
        {
            _defaultLCID = defaultLCID;
        }

        /// <summary>
        /// Add a localized text string.
        /// </summary>
        /// <param name="lcid">locale</param>
        /// <param name="name">Name identifying the string. Used to fetch the string later on.</param>
        /// <param name="text">Localized string</param>
        public abstract void Add(string name, int lcid, string text);

		/// <summary>
		/// Sets a localized text string. If the a string with the specified name exists it will be overwritten.
		/// </summary>
		/// <param name="lcid">locale</param>
		/// <param name="name">Name identifying the string. Used to fetch the string later on.</param>
		/// <param name="text">Localized string</param>
    	public abstract void Set(string name, int lcid, string text);

        /// <summary>
        /// Adds a sub category
        /// </summary>
        /// <param name="name">Name of the sub category</param>
        /// <exception cref="ArgumentException">If a category with the specified name already exists</exception>
        /// <exception cref="ArgumentNullException">If name is null</exception>
        public abstract LanguageNode AddNode(string name);

        /// <summary>
        /// Retrieves a subcategory
        /// </summary>
        /// <param name="name">The category name</param>
        /// <returns>Null if the category does not exist</returns>
        /// <exception cref="ArgumentNullException">If name is null</exception>
        public LanguageNode GetNode(string name)
        {
            if(string.IsNullOrEmpty(name))
                throw new ArgumentNullException("name");

            return !_subNodes.ContainsKey(name) ? Empty : _subNodes[name];
        }

        /// <summary>
        /// Retrieves a sub node or null if the requested sub node does not exist
        /// </summary>
        /// <param name="name">Name of the parameter</param>
        /// <returns>The named <see cref="LanguageNode"/> or null</returns>
        /// <exception cref="ArgumentNullException">If name is null or empty</exception>
        public LanguageNode GetNodeUnsafe(string name)
        {
            if(string.IsNullOrEmpty(name))
                throw new ArgumentNullException("name");

            return _subNodes.ContainsKey(name) ? _subNodes[name] : null;
        }

        /// <summary>
        /// Get a localized text string in the current language.
        /// </summary>
        /// <param name="textName">Phrase to find.</param>
        /// <returns>text if found; [textName] if not.</returns>
        /// <example>
        /// <code>
        /// lang["Name"] // => "Name"
        /// lang["Naem"] // => "[Naem]" since it's missing
        /// </code>
        /// </example>
        public abstract string this[string textName] { get; }

        /// <summary>
        /// Get a localized text string
        /// </summary>
        /// <param name="lcid"></param>
        /// <param name="textName">Phrase to find.</param>
        /// <returns>text if found; [textName] if not.</returns>
        /// <example>
        /// <code>
        /// lang["Name"] // => "Name"
        /// lang["Naem"] // => "[Naem]" since it's missing
        /// </code>
        /// </example>
        public abstract string this[string textName, int lcid] { get; }

        /// <summary>
        /// Number languages
        /// </summary>
        public abstract int Count
        { get;}

        /// <summary>
        /// Returns the name of the node
        /// </summary>
        public string Name
        {
            get { return _name; }
            internal set{ _name = value;}
        }

        /// <summary>
        /// LCID to use if the specified or current LCID is not found.
        /// </summary>
        public int DefaultLCID
        {
            get { return _defaultLCID; }
        }

        /// <summary>
        /// Number of translated texts in the specified language
        /// </summary>
        /// <param name="lcid"></param>
        /// <returns></returns>
        public abstract int GetTextCount(int lcid);

        /// <summary>
        /// Value that should be returned if the text is not found.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string EmptyValue(string name)
        {
            return string.Format("[{0}]", name);
        }

        /// <summary>
        /// Set default locale
        /// </summary>
        /// <param name="lcid">Locale to set.</param>
        internal void SetDefaultLCID(int lcid)
        {
            _defaultLCID = lcid;
        }

        /// <summary>
        /// Determine if a category contains a specific language.
        /// </summary>
        /// <param name="lcid"></param>
        /// <returns></returns>
        public abstract bool Contains(int lcid);

        /// <summary>Empties all saved values in the node and its sub nodes</summary>
        public abstract void ClearHierarchy();
    }

}

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 GNU Lesser General Public License (LGPLv3)


Written By
Founder 1TCompany AB
Sweden Sweden

Comments and Discussions