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