/// <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); }