protected XmlSchemaComplexType FindOrCreateComplexType(Type t) { XmlSchemaComplexType ct; string typeId = GenerateIDFromType(t); ct = FindComplexTypeByID(typeId); if (ct != null) { return(ct); } ct = new XmlSchemaComplexType(); ct.Name = typeId; // Force mixed attribute for tasks names in the mixedTaskNames array. Fixes Bug#: 3058913 if (Array.IndexOf(mixedTaskNames, ct.Name) != -1) { ct.IsMixed = true; } // add complex type to collection immediately to avoid stack // overflows, when we allow a type to be nested _nantComplexTypes.Add(typeId, ct); #if NOT_IMPLEMENTED // // TODO - add task/type documentation in the future // ct.Annotation = new XmlSchemaAnnotation(); XmlSchemaDocumentation doc = new XmlSchemaDocumentation(); ct.Annotation.Items.Add(doc); doc.Markup = ...; #endif XmlSchemaSequence group1 = null; XmlSchemaObjectCollection attributesCollection = ct.Attributes; foreach (MemberInfo memInfo in t.GetMembers(BindingFlags.Instance | BindingFlags.Public)) { if (memInfo.DeclaringType.Equals(typeof(object))) { continue; } //Check for any return type that is derived from Element // add Attributes TaskAttributeAttribute taskAttrAttr = (TaskAttributeAttribute) Attribute.GetCustomAttribute(memInfo, typeof(TaskAttributeAttribute), false); BuildElementAttribute buildElemAttr = (BuildElementAttribute) Attribute.GetCustomAttribute(memInfo, typeof(BuildElementAttribute), false); if (taskAttrAttr != null) { XmlSchemaAttribute newAttr = CreateXsdAttribute(taskAttrAttr.Name, taskAttrAttr.Required); attributesCollection.Add(newAttr); } else if (buildElemAttr != null) { // Create individial choice for any individual child Element Decimal min = 0; if (buildElemAttr.Required) { min = 1; } XmlSchemaElement childElement = new XmlSchemaElement(); childElement.MinOccurs = min; childElement.MaxOccurs = 1; childElement.Name = buildElemAttr.Name; //XmlSchemaGroupBase elementGroup = CreateXsdSequence(min, Decimal.MaxValue); Type childType; // We will only process child elements if they are defined for Properties or Fields, this should be enforced by the AttributeUsage on the Attribute class if (memInfo is PropertyInfo) { childType = ((PropertyInfo)memInfo).PropertyType; } else if (memInfo is FieldInfo) { childType = ((FieldInfo)memInfo).FieldType; } else if (memInfo is MethodInfo) { MethodInfo method = (MethodInfo)memInfo; if (method.GetParameters().Length == 1) { childType = method.GetParameters()[0].ParameterType; } else { throw new ApplicationException("Method should have one parameter."); } } else { throw new ApplicationException("Member Type != Field/Property/Method"); } BuildElementArrayAttribute buildElementArrayAttribute = (BuildElementArrayAttribute) Attribute.GetCustomAttribute(memInfo, typeof(BuildElementArrayAttribute), false); // determine type of child elements if (buildElementArrayAttribute != null) { if (buildElementArrayAttribute.ElementType == null) { if (childType.IsArray) { childType = childType.GetElementType(); } else { Type elementType = null; // locate Add method with 1 parameter, type of that parameter is parameter type foreach (MethodInfo method in childType.GetMethods(BindingFlags.Public | BindingFlags.Instance)) { if (method.Name == "Add" && method.GetParameters().Length == 1) { ParameterInfo parameter = method.GetParameters()[0]; elementType = parameter.ParameterType; break; } } childType = elementType; } } else { childType = buildElementArrayAttribute.ElementType; } if (childType == null || !typeof(Element).IsAssignableFrom(childType)) { throw new BuildException(string.Format(CultureInfo.InvariantCulture, ResourceUtils.GetString("NA1140"), memInfo.DeclaringType.FullName, memInfo.Name)); } } BuildElementCollectionAttribute buildElementCollectionAttribute = (BuildElementCollectionAttribute)Attribute.GetCustomAttribute(memInfo, typeof(BuildElementCollectionAttribute), false); if (buildElementCollectionAttribute != null) { XmlSchemaComplexType collectionType = new XmlSchemaComplexType(); XmlSchemaSequence sequence = new XmlSchemaSequence(); collectionType.Particle = sequence; sequence.MinOccurs = 0; sequence.MaxOccursString = "unbounded"; XmlSchemaElement itemType = new XmlSchemaElement(); itemType.Name = buildElementCollectionAttribute.ChildElementName; itemType.SchemaTypeName = FindOrCreateComplexType(childType).QualifiedName; sequence.Items.Add(itemType); childElement.SchemaType = collectionType; } else { childElement.SchemaTypeName = FindOrCreateComplexType(childType).QualifiedName; } // lazy init of sequence if (group1 == null) { group1 = CreateXsdSequence(0, Decimal.MaxValue); ct.Particle = group1; } group1.Items.Add(childElement); } } // allow attributes from other namespace ct.AnyAttribute = new XmlSchemaAnyAttribute(); ct.AnyAttribute.Namespace = "##other"; ct.AnyAttribute.ProcessContents = XmlSchemaContentProcessing.Skip; Schema.Items.Add(ct); Compile(); return(ct); }
protected override bool InitializeBuildElementCollection(System.Reflection.PropertyInfo propertyInfo) { Type elementType = typeof(Filter); BuildElementArrayAttribute buildElementArrayAttribute = (BuildElementArrayAttribute) Attribute.GetCustomAttribute(propertyInfo, typeof(BuildElementArrayAttribute)); if (buildElementArrayAttribute == null || propertyInfo.PropertyType != typeof(FilterCollection)) { return(base.InitializeBuildElementCollection(propertyInfo)); } XmlNodeList collectionNodes = ElementXml.ChildNodes; // create new array of the required size - even if size is 0 ArrayList list = new ArrayList(collectionNodes.Count); foreach (XmlNode childNode in collectionNodes) { // skip non-nant namespace elements and special elements like comments, pis, text, etc. if (!(childNode.NodeType == XmlNodeType.Element) || !childNode.NamespaceURI.Equals(NamespaceManager.LookupNamespace("nant"))) { continue; } // remove element from list of remaining items UnprocessedChildNodes.Remove(childNode.Name); // initialize child element (from XML or data type reference) Filter filter = TypeFactory.CreateFilter(childNode, Element); list.Add(filter); } MethodInfo addMethod = null; // get array of public instance methods MethodInfo[] addMethods = propertyInfo.PropertyType.GetMethods(BindingFlags.Public | BindingFlags.Instance); // search for a method called 'Add' which accepts a parameter // to which the element type is assignable foreach (MethodInfo method in addMethods) { if (method.Name == "Add" && method.GetParameters().Length == 1) { ParameterInfo parameter = method.GetParameters()[0]; if (parameter.ParameterType.IsAssignableFrom(elementType)) { addMethod = method; break; } } } if (addMethod == null) { throw new BuildException(string.Format(CultureInfo.InvariantCulture, ResourceUtils.GetString("NA1020"), elementType.FullName, propertyInfo.PropertyType.FullName, propertyInfo.Name, Name), Location); } // if value of property is null, create new instance of collection object collection = propertyInfo.GetValue(Element, BindingFlags.Default, null, null, CultureInfo.InvariantCulture); if (collection == null) { if (!propertyInfo.CanWrite) { throw new BuildException(string.Format(CultureInfo.InvariantCulture, ResourceUtils.GetString("NA1093"), buildElementArrayAttribute.Name, Name), Location); } object instance = Activator.CreateInstance( propertyInfo.PropertyType, BindingFlags.Public | BindingFlags.Instance, null, null, CultureInfo.InvariantCulture); propertyInfo.SetValue(Element, instance, BindingFlags.Default, null, null, CultureInfo.InvariantCulture); } // add each element of the arraylist to collection instance foreach (object childElement in list) { addMethod.Invoke(collection, BindingFlags.Default, null, new object[] { childElement }, CultureInfo.InvariantCulture); } return(true); }