protected void InitValues(ComponentInitInfo componentInit, XPathNavigator componentNode, IXmlNamespaceResolver xmlNs, IDictionary <string, ComponentInitInfo> componentInfoByName) { Dictionary <int, IValueInitInfo> constructorArgs = new Dictionary <int, IValueInitInfo>(); List <IPropertyInitInfo> propsList = new List <IPropertyInitInfo>(); Dictionary <string, int> propsIndex = new Dictionary <string, int>(); // parent exists? if (componentInit.Parent != null) { IComponentInitInfo parentComponentInfo = componentInfoByName[componentInit.Parent]; if (parentComponentInfo == null) { throw new Exception("Cannot find parent component with name='" + componentInit.Parent + "'"); } // copy all property-definitions for (int i = 0; i < parentComponentInfo.Properties.Length; i++) { propsList.Add(parentComponentInfo.Properties[i]); propsIndex[parentComponentInfo.Properties[i].Name] = i; } // copy all constructor-arg-definitions for (int i = 0; i < parentComponentInfo.ConstructorArgs.Length; i++) { constructorArgs[i] = parentComponentInfo.ConstructorArgs[i]; } // copy type attribute (if not set) if (componentInit.ComponentType == null) { componentInit.ComponentType = parentComponentInfo.ComponentType; } // copy init method attribute (if not set) if (componentInit.InitMethod == null) { componentInit.InitMethod = parentComponentInfo.InitMethod; } } // extract constructor arguments var constructorArgNodes = componentNode.Select("ioc:constructor-arg", xmlNs); var autoIdx = 0; while (constructorArgNodes.MoveNext()) { var constructorArgNode = constructorArgNodes.Current; var indexAttr = constructorArgNode.GetAttribute("index", String.Empty); int index = !String.IsNullOrEmpty(indexAttr) ? Convert.ToInt32(indexAttr) : autoIdx; var explicitArgName = constructorArgNode.GetAttribute("name", String.Empty); if (!String.IsNullOrEmpty(explicitArgName)) { // try to find argument by name var paramByNameFound = false; foreach (var constrInfo in componentInit.ComponentType.GetConstructors()) { var cParams = constrInfo.GetParameters(); if (cParams.Length == constructorArgNodes.Count) { for (int i = 0; i < cParams.Length; i++) { if (cParams[i].Name == explicitArgName) { index = cParams[i].Position; paramByNameFound = true; break; } } } if (paramByNameFound) { break; } } if (!paramByNameFound) { throw new Exception(String.Format("Cannot find constructor argument by name='{0}' for component (name='{1}', type='{2}')", explicitArgName, componentInit.Name, componentInit.ComponentType)); } } try { constructorArgs[index] = ResolveValueInfo(constructorArgNode, xmlNs, componentInfoByName); } catch (Exception ex) { throw new XmlConfigurationException( String.Format("Cannot resolve value for constructor arg #{0}", index), ex); } autoIdx++; } // compose final constructor args list // 1) find greatest index int maxConstructorArgIndex = -1; foreach (int idx in constructorArgs.Keys) { if (idx > maxConstructorArgIndex) { maxConstructorArgIndex = (int)idx; } } // 2) create constructor args array componentInit.ConstructorArgs = new IValueInitInfo[maxConstructorArgIndex + 1]; // 3) initialize constructor args array foreach (int idx in constructorArgs.Keys) { componentInit.ConstructorArgs[idx] = constructorArgs[idx]; } // extract properies var propertyNodes = componentNode.Select("ioc:property", xmlNs); while (propertyNodes.MoveNext()) { var propertyNode = propertyNodes.Current; var propNameAttr = propertyNode.GetAttribute("name", String.Empty); try { PropertyInfo pInfo = new PropertyInfo( propNameAttr, ResolveValueInfo(propertyNode, xmlNs, componentInfoByName)); if (propsIndex.ContainsKey(pInfo.Name)) { propsList[propsIndex[pInfo.Name]] = pInfo; } else { int idx = propsList.Count; propsList.Add(pInfo); propsIndex[pInfo.Name] = idx; } } catch (Exception ex) { throw new XmlConfigurationException( String.Format("Cannot resolve value for property '{0}' of component '{1}'", propNameAttr, componentInit.Name), ex); } } // compose final properties list componentInit.Properties = propsList.ToArray(); }
protected IValueInitInfo ResolveValueInfo(XPathNavigator objectDefinition, IXmlNamespaceResolver xmlNs, IDictionary <string, ComponentInitInfo> components) { // component definition ? var componentNode = objectDefinition.SelectSingleNode("ioc:component", xmlNs); if (componentNode != null) { // build nested component init info ComponentInitInfo nestedComponentInfo = ReadComponentInitInfo(componentNode, xmlNs); InitValues(nestedComponentInfo, componentNode, xmlNs, components); return(new RefValueInfo(nestedComponentInfo)); } // reference ? var refNode = objectDefinition.SelectSingleNode("ioc:ref", xmlNs); if (refNode != null) { string refName = refNode.GetAttribute("name", String.Empty); if (!components.ContainsKey(refName)) { throw new NullReferenceException("Reference to non-existent component: " + refName); } string methodName = refNode.GetAttribute("method", String.Empty); if (methodName.Trim() == String.Empty) { methodName = null; } return(new RefValueInfo(components[refName], methodName)); } // value ? var valueNode = objectDefinition.SelectSingleNode("ioc:value", xmlNs); if (valueNode != null) { return(new ValueInitInfo(valueNode.Value)); } // xml ? var xmlNode = objectDefinition.SelectSingleNode("ioc:xml", xmlNs); if (xmlNode != null) { return(new ValueInitInfo(xmlNode.InnerXml)); } // System.Type reference ? var typeNode = objectDefinition.SelectSingleNode("ioc:type", xmlNs); if (typeNode != null) { return(new TypeValueInitInfo(TypeResolver.ResolveType(typeNode.InnerXml))); } // list ? var listNode = objectDefinition.SelectSingleNode("ioc:list", xmlNs); if (listNode != null) { var entryNodes = listNode.Select("ioc:entry", xmlNs); IValueInitInfo[] entries = new IValueInitInfo[entryNodes.Count]; int listEntryIdx = 0; while (entryNodes.MoveNext()) { entries[listEntryIdx++] = ResolveValueInfo(entryNodes.Current, xmlNs, components); } return(new ListValueInitInfo(entries)); } // map ? var mapNode = objectDefinition.SelectSingleNode("ioc:map", xmlNs); if (mapNode != null) { var entryNodes = mapNode.Select("ioc:entry", xmlNs); MapEntryInfo[] entries = new MapEntryInfo[entryNodes.Count]; int mapEntryIndex = 0; while (entryNodes.MoveNext()) { entries[mapEntryIndex++] = new MapEntryInfo( entryNodes.Current.GetAttribute("key", String.Empty), ResolveValueInfo(entryNodes.Current, xmlNs, components)); } return(new MapValueInitInfo(entries)); } // unknown object definition (???) throw new XmlConfigurationException("Unknown object definition"); }
protected ComponentInitInfo ReadComponentInitInfo(XPathNavigator componentNode, IXmlNamespaceResolver xmlNs) { var componentInit = new ComponentInitInfo(); // extract component name (optional) var nameAttr = componentNode.GetAttribute("name", String.Empty); if (!String.IsNullOrEmpty(nameAttr)) { componentInit.Name = nameAttr; } // extract component parent (optional) var parentAttr = componentNode.GetAttribute("parent", String.Empty); if (!String.IsNullOrEmpty(parentAttr)) { componentInit.Parent = parentAttr; } // extract component type (optional) var typeAttr = componentNode.GetAttribute("type", String.Empty); if (!String.IsNullOrEmpty(typeAttr)) { try { componentInit.ComponentType = TypeResolver.ResolveType(typeAttr); } catch (Exception ex) { throw new XmlConfigurationException(ex.Message, ex); } if (componentInit.ComponentType == null) { throw new XmlConfigurationException("Cannot resolve type " + typeAttr); } } // extract component lazy init flag componentInit.LazyInit = DefaultLazyInit; var lazyInitAttr = componentNode.GetAttribute("lazy-init", String.Empty); if (!String.IsNullOrEmpty(lazyInitAttr)) { componentInit.LazyInit = Convert.ToBoolean(lazyInitAttr); } // extract component singleton flag var singletonAttr = componentNode.GetAttribute("singleton", String.Empty); if (!String.IsNullOrEmpty(singletonAttr)) { componentInit.Singleton = Convert.ToBoolean(singletonAttr); } // extract init-method value var initMethodAttr = componentNode.GetAttribute("init-method", String.Empty); if (!String.IsNullOrEmpty(initMethodAttr)) { componentInit.InitMethod = initMethodAttr; } // extract description value var descriptionNode = componentNode.SelectSingleNode("ioc:description", xmlNs); if (descriptionNode != null) { componentInit.Description = descriptionNode.Value; } return(componentInit); }