/// <summary>
        /// Makes a association between an element and a native element class.
        /// </summary><remarks>
        /// In case of an already created object the object is returned instead of creating a new one.
        /// This class returns <see cref="System.Web.UI.Control">Control</see>, but all element classes internally
        /// used are using IElement, too. So in any case an internal HTML element object is being retrieved, it's
        /// possible to cast to IElement instead. In case of a plug-in this is not required, because plug-ins may handle
        /// their elements differently and such a cast is not appropriate. Consult the documentation of the plug-in to
        /// understand the requirements for object handling.
        /// </remarks>
        /// <param name="el">The element for that a native object is needed.</param>
        /// <returns>System.Web.UI.Control if creating or retrieving was successful, otherwise <c>null</c>. The caller is responsible to cast to the right class type.</returns>
        public Control CreateElement(Interop.IHTMLElement el)
        {
            if (el == null)
            {
                return(null);
            }

            Type    type    = null;
            Control element = null;
            // each element will be stored in a hashtable to increase performance, subsequent calls
            // to this factory will retrieve stored objects instead of creating new ones.
            string uniqueName;

            ((Interop.IHTMLUniqueName)el).uniqueID(out uniqueName);
            // look whether we have it already in the designer
            if (designerHost[uniqueName] is Control)
            {
                Control returnEl = designerHost[uniqueName] as Control;
                if (returnEl is IElement)
                {
                    ((IElement)returnEl).HtmlEditor = this.htmlEditor;
                }
                return(returnEl);
            }
            // if not, try plug-ins, and finally add
            try
            {
                // get tag name
                type = GetElementType(el);
                ConstructorInfo cinfo;
                if (type != null)
                {
                    // default ctor
                    cinfo = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(Interop.IHTMLElement), typeof(IHtmlEditor) }, null);
                    // not found - get it from plug-in
                    if (cinfo == null)
                    {
                        // probably an plugin-driven control, plug-ins register their elements in designer host
                        foreach (IComponent icomp in designerHost.Container.Components)
                        {
                            IDesigner id = designerHost.GetDesigner(icomp);
                            if (id == null)
                            {
                                continue;
                            }
                            if (id is ControlDesigner)
                            {
                                IHtmlControlDesignerBehavior db = ((ControlDesigner)id).Behavior as IHtmlControlDesignerBehavior;
                                if (db != null && db.DesignTimeElement.Equals(el))
                                {
                                    element = icomp as Control;
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        // usually, we get and invoke here
                        element = (Control)cinfo.Invoke(new object[] { el, htmlEditor });
                    }
                    // still not found, try other ctors plugins- could usually define
                    while (element == null)
                    {
                        //throw new NotSupportedException("Element " + ns + ":" + str1 + " not supported. Did you miss a registration?");
                        cinfo = type.GetConstructor(new Type[] { typeof(Interop.IHTMLElement), typeof(IHtmlEditor) });
                        if (cinfo != null)
                        {
                            element = (Control)cinfo.Invoke(new object[] { el, htmlEditor });
                            break;
                        }
                        cinfo = type.GetConstructor(new Type[] { typeof(IHtmlEditor) });
                        if (cinfo != null)
                        {
                            element = (Control)cinfo.Invoke(new object[] { htmlEditor });
                            break;
                        }
                        cinfo = type.GetConstructor(Type.EmptyTypes);
                        if (cinfo != null)
                        {
                            element = (Control)cinfo.Invoke(null);
                            break;
                        }
                    }
                }
            }
            catch
            {
                // whatever is goind wrong we don't care, returning null is "bad state" for caller
                //return null;
                throw;
            }
            finally
            {
                if (element != null)
                {
                    if (element is IElement)
                    {
                        ((IElement)element).HtmlEditor = this.htmlEditor;
                    }
                    // not there, then we add it
                    if (designerHost[uniqueName] == null)
                    {
                        designerHost.Add(element, uniqueName);
                        ((HtmlEditor)htmlEditor).OnElementCreated(element);
                    }
                }
            }
            return(element);
        }