Reflection C#

// this class is documented here:
// http://blog.thekieners.com/2010/09/06/type-gettype-implementation-with-help-of-xamlreader/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Markup;
using System.Windows.Media;
namespace Nova.Core.Common
{
    /// 
    /// Provides functionality to load any type with its class name, namespace and assembly-name within the Silverlight environment.
    /// 

    /// 
    /// The Type.GetType method is different in Silverlight than in the standard .NET runtime. In Silverlight we have to provide the 
    /// fully qualified assembly name to get a type in a custom assembly. Only build in controls or types in the same assembly are 
    /// excluded from this rule. Full qualified assembly name means a syntax like the following: 
    /// MyComponent.MyType, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4bec85d7bec6698f.
    /// This class uses the XamlReader capability to resolve type during parsing a xaml-string. While this is a little time consuming
    /// the TypeLoader maintains a cache to get types faster.
    /// 

    public static class TypeLoader
    {
        // cache for resolved type
        private static readonly Dictionary _cache = new Dictionary();
        /// 
        /// Gets the System.Type with the specified name, name space and assembly name.
        /// 

        /// The class name without namespace.
        /// The name space
        /// The name of the assembly containing the type.
        /// The type matching the provided parameters or null if not found.
        //[DebuggerStepThrough()]
        public static Type GetType(string className, string nameSpace, string assemblyName)
        {
            // check
            if (StringHelper.IsNullOrWhiteSpace(nameSpace))
                return null;
            string xamlNamespace = string.Format("clr-namespace:{0}", nameSpace);
            // assembly name is optional
            if (!StringHelper.IsNullOrWhiteSpace(assemblyName))
                xamlNamespace += string.Format(";assembly={0}", assemblyName);
            return GetType(className, xamlNamespace);
        }
        /// 
        /// Gets the System.Type with the specified name. 
        /// This method overload can be used for:
        /// 1. core controls such as Button, Grid, ListBox, etc. without specifying the namespace or assembly name.
        /// 2. with the qualified assembly name of the type without version and public key token like this: "MyNamespace.MyType, MyAssembly".
        /// 

        /// Pure class name of Core Controls such as Button, Grid, ListBox, etc.
        /// The type matching the provided parameters or null if not found.
        //[DebuggerStepThrough()]
        public static Type GetType(string className)
        {
            if (className != null && className.Contains(","))
            {
                string[] qualifiedNameParts = className.Split(',');
                if (qualifiedNameParts.Length == 2)
                {
                    string[] fullClassNameParts = qualifiedNameParts[0].Split('.');
                    if (fullClassNameParts.Length > 0)
                    {
                        // classname
                        string newClassName = fullClassNameParts.Last().Trim();
                        // namespace
                        string nameSpace = "";
                        for (int i = 0; i < fullClassNameParts.Length - 1; i++)
                        {
                            nameSpace += fullClassNameParts[i] + ".";
                        }
                        nameSpace = nameSpace.TrimEnd('.');
                        string assemblyName = qualifiedNameParts[1].Trim();
                        return GetType(newClassName, nameSpace, assemblyName);
                    }
                }
            }
            return GetType(className, "");
        }
        /// 
        /// Gets the System.Type with the specified name. The xaml namespace specifies the namespace and assembly name in the same syntax as in xaml. 
        /// 

        /// The class name without namespace.
        /// 
        /// The xaml namespace. This is the same syntax as used in XAML syntax. 
        /// Example: "clr-namespace:MyComponent.SubNamespace;assembly=MyAssemblyName
        /// 
        /// The type matching the provided parameters or null if not found.
        //[DebuggerStepThrough()]
        public static Type GetType(string className, string xamlNamespace)
        {
            // check input
            if (StringHelper.IsNullOrWhiteSpace(className))
                return null;
            if (className.Contains("."))
                throw new ArgumentException(
                    "className must not include the namespace. Please provide namespace with separate parameter.");
            // check if type is already in cache
            string key = xamlNamespace + "&" + className;
            if (_cache.ContainsKey(key))
                return _cache[key];
            lock (_cache)
            {
                try
                {
                    // check again because another thread might be faster and has already created the cache-entry
                    if (_cache.ContainsKey(key))
                        return _cache[key];
                    // create xaml with a simply Style element and set the TargetType property with the provided type name
                    string xaml = "                    // set the xaml namesapce if provided
                    if (!StringHelper.IsNullOrWhiteSpace(xamlNamespace))
                    {
                        xaml += string.Format("xmlns:tmp='{0}' TargetType='tmp:{1}' />", xamlNamespace, className);
                    }
                    else
                    {
                        // Core controls such as Button, Grid, ListBox, etc do not need a namespace
                        xaml += string.Format("TargetType='{0}' />", className);
                    }
                    // let the XamlParser load the type via the TargetType property 
                    var style = XamlReader.Load(xaml) as Style;
                    if (style != null)
                    {
                        Type targetType = style.TargetType;
                        AddToCache(key, targetType);
                        return targetType;
                    }
                }
                catch (Exception ex)
                {
                    // Try to load type in executing assembly
                    if (!StringHelper.IsNullOrWhiteSpace(xamlNamespace))
                    {
                        // note: Type.GetType uses needs assembly-qualified name of the type to get. If the type is 
                        //       in the currently executing assembly or in Mscorlib.dll, it is sufficient to supply 
                        //       the type name qualified by its namespace.
                        Type type =
                            Type.GetType(string.Format("{0}.{1}",
                                                       xamlNamespace.Replace("clr-namespace:", "").TrimEnd(';'),
                                                       className));
                        if (type != null)
                        {
                            // add to cache
                            AddToCache(key, type);
                            return type;
                        }
                    }
                    //****** DONT SET VALUE TO NULL, BECAUSE OF CASES WHEN AN ASSEMBLY IS  *****
                    //****** LOADED DYNAMICALLY INTO THE APPLICATION DOMAIN                *****
                    // don't let the exception repeat. Set null as cache value
                    AddToCache(key, null);
                    //**************************************************************************/
                }
            }
            return null;
        }
        private static void AddToCache(string key, Type type)
        {
            _cache.Add(key, type);
            CompositionTarget.Rendering -= CompositionTarget_Rendering;
            CompositionTarget.Rendering += CompositionTarget_Rendering;
        }
        private static void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            CompositionTarget.Rendering -= CompositionTarget_Rendering;
            _cache.Clear();
        }
        #region Nested type: StringHelper
        private static class StringHelper
        {
            // helper because .NET 3.5 does not support IsNullOrWhiteSpace
            public static bool IsNullOrWhiteSpace(string str)
            {
                if (str == null)
                    return true;
                if (str.Trim() == string.Empty)
                    return true;
                return false;
            }
        }
        #endregion
    }
}