private IElement CreateElement(RenderContext renderContext, XmlNode currentNode, IEnumerable<Type> availableTypes) { var nodeName = currentNode.LocalName; Type controlType = availableTypes.SingleOrDefault(a => a.GetCustomAttributes(typeof(ElementNameAttribute), false).Cast<ElementNameAttribute>().Any(c => c.ElementName.Equals(nodeName))); if (controlType == null) { throw new ControlNotSupportedException($"Control {nodeName} is not supported."); } IElement element = (IElement)Activator.CreateInstance(controlType, renderContext); foreach(XmlAttribute attribute in currentNode.Attributes) { // skip namespaced attributes, they belong to other implementations. if (attribute.Name.Contains(":")) continue; PropertyInfo property = controlType.GetProperties().SingleOrDefault(p => p.GetCustomAttributes(typeof(AttributeNameAttribute), false).Cast<AttributeNameAttribute>().Any(c => c.Name.Equals(attribute.Name))); if (property != null) { if (property.PropertyType == typeof(Boolean)) { property.SetValue(element, Boolean.Parse(attribute.Value)); } else { property.SetValue(element, attribute.Value); } } else { throw new AttributeNotSupportedException($"Control {nodeName} is does not support attribute {attribute.Name}."); } } IElementContainer container = element as IElementContainer; if (container != null) { var childNodes = currentNode.ChildNodes; foreach (XmlNode node in childNodes) { container.Elements.Add(CreateElement(renderContext, node, availableTypes)); } return container; } return element; }
public IWebControlTemplate BindTemplate(IElement element, RenderContext renderContext) { Type type = element.GetType(); var types = this.GetType().Assembly.GetTypes().Where(t => typeof(IWebControlTemplate).IsAssignableFrom(t)); Type template = types.Where(t => t.GetInterfaces().Any(i => i.IsGenericType && i.GenericTypeArguments.All(a => a.Equals(type)))).Single(t => typeof(IWebControlTemplate).IsAssignableFrom(t)); var templateInstance = (IWebControlTemplate)Activator.CreateInstance(template, element, renderContext); var collectionTemplate = templateInstance as IWebControlCollectionTemplate; if (collectionTemplate != null) { var elementContainer = element as IElementContainer; foreach(IElement childElement in elementContainer.Elements) { collectionTemplate.ChildTemplates.Add(BindTemplate(childElement, renderContext)); } } return templateInstance; }
public WebRequestOutput Create(string applicationPath, Uri uri, XmlDocument xmlDocument) { if (uri == null) throw new ArgumentNullException(nameof(uri)); if (xmlDocument == null) throw new ArgumentNullException(nameof(xmlDocument)); StringBuilder stringBuilder = new StringBuilder(); TextWriter textWriter = new StringWriter(stringBuilder); RenderContext renderContext = new RenderContext(new HtmlTextWriter(textWriter), referenceService, uri, applicationPath); WebRequestOutput output = new WebRequestOutput { ContentType = "text/html" }; IEnumerable<Type> availableTypes = this.GetType().Assembly.GetTypes().Where(t => typeof(IElement).IsAssignableFrom(t) && t.IsAbstract == false && t.IsInterface == false); var currentNode = xmlDocument.SelectSingleNode("/*[1]"); try { var element = CreateElement(renderContext, currentNode, availableTypes); var template = controlTemplateBinder.BindTemplate(element, renderContext); // TODO: Initialization to add scripts. template.Render(); output.Response = stringBuilder.ToString(); renderContext.HtmlTextWriter.Close(); } catch(ControlNotSupportedExecption cne) { output.Error = new ControlNotSupportedError(cne.NodeName); } return output; }