/// <summary>
        /// Determines the icon to show in a compartment entry, based on its properties.
        /// </summary>
        /// <param name="element">The configuration property being shown in the compartment.</param>
        /// <returns>The icon to use to represent the configuration property.</returns>
        private Image CompartmentImageProvider(ModelElement element)
        {
            // Show icons.
            ConfigurationProperty prop = (ConfigurationProperty)element;

            if (prop is AttributeProperty)
            {
                if (prop.IsKey)
                {
                    return(Resources.KeyProperty);
                }
                else if (prop.IsRequired)
                {
                    return(Resources.RequiredProperty);
                }
                else
                {
                    return(Resources.Property);
                }
            }
            else if (prop is ElementProperty)
            {
                if (prop.IsKey)
                {
                    return(Resources.KeyElement);
                }
                else if (prop.IsRequired)
                {
                    return(Resources.RequiredElement);
                }
                else
                {
                    return(Resources.Element);
                }
            }
            return(null);
        }
        private void GenerateConverter(CodeMemberProperty propertyProperty, ConfigurationProperty property)
        {
            CodeAttributeDeclaration converterAttribute = new CodeAttributeDeclaration(GlobalReference(typeof(System.ComponentModel.TypeConverter)));

            propertyProperty.CustomAttributes.Add(converterAttribute);

            CodeTypeOfExpression converterType = null;

            switch (property.TypeConverter)
            {
            case TypeConverters.Custom:
                CustomTypeConverter custom = property.CustomTypeConverter;
                if (custom == null)
                {
                    throw new ApplicationException("The type converter specified is 'Custom', but no valid 'Custom Type Converter' was selected.");
                }
                converterType = new CodeTypeOfExpression(GlobalSelfReference(string.Format("{0}.{1}", custom.ConfigurationSectionModel.Namespace, custom.Name)));
                break;

            case TypeConverters.CommaDelimitedStringCollectionConverter:
                converterType = new CodeTypeOfExpression(GlobalReference(typeof(System.Configuration.CommaDelimitedStringCollectionConverter)));
                break;

            case TypeConverters.GenericEnumConverter:
                //converterType = new CodeTypeOfExpression( GlobalReference( typeof( System.Configuration.GenericEnumConverter ) ) );
                // The framework automatically calls this for enums, so do not manually set it or else ctor error occurs.
                // http://stackoverflow.com/questions/9687795/error-reading-custom-configuration-section-no-parameterless-constructor-defined
                converterType = null;
                break;

            case TypeConverters.InfiniteIntConverter:
                converterType = new CodeTypeOfExpression(GlobalReference(typeof(System.Configuration.InfiniteIntConverter)));
                break;

            case TypeConverters.InfiniteTimeSpanConverter:
                converterType = new CodeTypeOfExpression(GlobalReference(typeof(System.Configuration.InfiniteTimeSpanConverter)));
                break;

            case TypeConverters.TimeSpanMinutesConverter:
                converterType = new CodeTypeOfExpression(GlobalReference(typeof(System.Configuration.TimeSpanMinutesConverter)));
                break;

            case TypeConverters.TimeSpanMinutesOrInfiniteConverter:
                converterType = new CodeTypeOfExpression(GlobalReference(typeof(System.Configuration.TimeSpanMinutesOrInfiniteConverter)));
                break;

            case TypeConverters.TimeSpanSecondsConverter:
                converterType = new CodeTypeOfExpression(GlobalReference(typeof(System.Configuration.TimeSpanSecondsConverter)));
                break;

            case TypeConverters.TimeSpanSecondsOrInfiniteConverter:
                converterType = new CodeTypeOfExpression(GlobalReference(typeof(System.Configuration.TimeSpanSecondsOrInfiniteConverter)));
                break;

            case TypeConverters.TypeNameConverter:
                converterType = new CodeTypeOfExpression(GlobalReference(typeof(System.Configuration.TypeNameConverter)));
                break;

            case TypeConverters.WhiteSpaceTrimStringConverter:
                converterType = new CodeTypeOfExpression(GlobalReference(typeof(System.Configuration.WhiteSpaceTrimStringConverter)));
                break;
            }
            if (converterType != null)
            {
                converterAttribute.Arguments.Add(new CodeAttributeArgument(converterType));
            }
        }
        private void GenerateConfigurationElementCollectionCode(ConfigurationElement element, CodeTypeDeclaration elementClass)
        {
            ConfigurationElementCollection collectionElement = (ConfigurationElementCollection)element;
            ConfigurationProperty          keyProperty       = collectionElement.ItemType.KeyProperties.Single();

            string xmlPropertyName = string.Format("{0}PropertyName", collectionElement.ItemType.Name);

            string configurationElementTypeReference           = GetTypeReferenceString(typeof(System.Configuration.ConfigurationElement));
            string configurationElementCollectionTypeReference = GetTypeReferenceString(typeof(System.Configuration.ConfigurationElementCollection));

            CodeTypeReference collectionItemType          = GlobalSelfReference(collectionElement.ItemType.FullName);
            string            collectionItemTypeReference = GetTypeSelfReferenceString(collectionElement.ItemType.FullName);

            CodeTypeReference icollectionTypeReference = null;

            if ((collectionElement.CodeGenOptions & ConfigurationElementCollectionCodeGenOptions.ICollection) == ConfigurationElementCollectionCodeGenOptions.ICollection)
            {
                icollectionTypeReference = new CodeTypeReference(string.Concat("global::System.Collections.Generic.ICollection<", collectionItemTypeReference, ">"));
                elementClass.BaseTypes.Add(icollectionTypeReference);
            }

            // Add ConfigurationCollectionAttribute
            CodeAttributeDeclaration collectionType =
                new CodeAttributeDeclaration(
                    GlobalReference(typeof(System.Configuration.ConfigurationCollectionAttribute)),
                    new CodeAttributeArgument(_selftypeof(collectionElement.ItemType.FullName)),
                    new CodeAttributeArgument("CollectionType",
                                              new CodeFieldReferenceExpression(
                                                  GlobalReferenceExpression(collectionElement.CollectionType.GetType()),
                                                  Enum.GetName(collectionElement.CollectionType.GetType(), collectionElement.CollectionType)
                                                  )
                                              )

                    );


            if (collectionElement.CollectionType == System.Configuration.ConfigurationElementCollectionType.BasicMap ||
                collectionElement.CollectionType == System.Configuration.ConfigurationElementCollectionType.BasicMapAlternate)
            {
                collectionType.Arguments.Add(
                    new CodeAttributeArgument("AddItemName",
                                              new CodeFieldReferenceExpression(
                                                  GlobalSelfReferenceExpression(element.FullName),
                                                  xmlPropertyName
                                                  )
                                              )
                    );
            }
            else
            {
                collectionType.Arguments.Add(
                    new CodeAttributeArgument("AddItemName",
                                              new CodePrimitiveExpression(collectionElement.AddItemName)
                                              )
                    );
                collectionType.Arguments.Add(
                    new CodeAttributeArgument("RemoveItemName",
                                              new CodePrimitiveExpression(collectionElement.RemoveItemName)
                                              )
                    );
                collectionType.Arguments.Add(
                    new CodeAttributeArgument("ClearItemsName",
                                              new CodePrimitiveExpression(collectionElement.ClearItemsName)
                                              )
                    );
            }

            elementClass.CustomAttributes.Add(collectionType);



            // Add XmlName field
            CodeMemberField xmlNameField = new CodeMemberField(_string, xmlPropertyName);

            elementClass.Members.Add(xmlNameField);
            xmlNameField.StartDirectives.Add(Region("Constants"));
            xmlNameField.Comments.Add(DocComment("<summary>"));
            xmlNameField.Comments.Add(DocComment(string.Format("The XML name of the individual <see cref=\"{0}\"/> instances in this collection.", collectionItemTypeReference)));
            xmlNameField.Comments.Add(DocComment("</summary>"));
            xmlNameField.CustomAttributes.Add(_generatedCodeAttribute);
            xmlNameField.Attributes     = MemberAttributes.Const | MemberAttributes.Assembly;
            xmlNameField.InitExpression = new CodePrimitiveExpression(collectionElement.XmlItemName);
            xmlNameField.EndDirectives.Add(EndRegion());

            // Add collection type property
            CodeMemberProperty collectionTypeProperty = new CodeMemberProperty();

            elementClass.Members.Add(collectionTypeProperty);
            collectionTypeProperty.StartDirectives.Add(Region("Overrides"));
            collectionTypeProperty.Comments.Add(DocComment("<summary>"));
            collectionTypeProperty.Comments.Add(DocComment(string.Format("Gets the type of the <see cref=\"{0}\"/>.", configurationElementCollectionTypeReference)));
            collectionTypeProperty.Comments.Add(DocComment("</summary>"));
            collectionTypeProperty.Comments.Add(DocComment(string.Format("<returns>The <see cref=\"{0}\"/> of this collection.</returns>", GetTypeReferenceString(typeof(System.Configuration.ConfigurationElementCollectionType)))));
            collectionTypeProperty.CustomAttributes.Add(_generatedCodeAttribute);
            collectionTypeProperty.Attributes = MemberAttributes.Public | MemberAttributes.Override;
            collectionTypeProperty.Type       = GlobalReference(typeof(System.Configuration.ConfigurationElementCollectionType));
            collectionTypeProperty.Name       = "CollectionType";
            collectionTypeProperty.HasGet     = true;
            collectionTypeProperty.GetStatements.Add(
                new CodeMethodReturnStatement(
                    new CodeFieldReferenceExpression(
                        GlobalReferenceExpression(collectionElement.CollectionType.GetType()),
                        Enum.GetName(collectionElement.CollectionType.GetType(), collectionElement.CollectionType)
                        )
                    )
                );

            // Add ElementName property
            CodeMemberProperty elementNameProperty = new CodeMemberProperty();

            elementClass.Members.Add(elementNameProperty);
            elementNameProperty.Comments.Add(DocComment("<summary>"));
            elementNameProperty.Comments.Add(DocComment("Gets the name used to identify this collection of elements"));
            elementNameProperty.Comments.Add(DocComment("</summary>"));
            elementNameProperty.CustomAttributes.Add(_generatedCodeAttribute);
            elementNameProperty.Attributes = MemberAttributes.Family | MemberAttributes.Override;
            elementNameProperty.Type       = _string;
            elementNameProperty.Name       = "ElementName";
            elementNameProperty.HasGet     = true;
            elementNameProperty.GetStatements.Add(
                new CodeMethodReturnStatement(
                    new CodeFieldReferenceExpression(
                        GlobalSelfReferenceExpression(element.FullName),
                        xmlPropertyName
                        )
                    )
                );

            // Add IsElementName method
            CodeMemberMethod isElementNameMethod = new CodeMemberMethod();

            elementClass.Members.Add(isElementNameMethod);
            isElementNameMethod.Comments.Add(DocComment("<summary>"));
            isElementNameMethod.Comments.Add(DocComment(string.Format("Indicates whether the specified <see cref=\"{0}\"/> exists in the <see cref=\"{1}\"/>.", configurationElementTypeReference, configurationElementCollectionTypeReference)));
            isElementNameMethod.Comments.Add(DocComment("</summary>"));
            isElementNameMethod.Comments.Add(DocComment("<param name=\"elementName\">The name of the element to verify.</param>"));
            isElementNameMethod.Comments.Add(DocComment("<returns>"));
            isElementNameMethod.Comments.Add(DocComment("<see langword=\"true\"/> if the element exists in the collection; otherwise, <see langword=\"false\"/>."));
            isElementNameMethod.Comments.Add(DocComment("</returns>"));
            isElementNameMethod.CustomAttributes.Add(_generatedCodeAttribute);
            isElementNameMethod.Attributes = MemberAttributes.Family | MemberAttributes.Override;
            isElementNameMethod.ReturnType = GlobalReference(typeof(bool));
            isElementNameMethod.Name       = "IsElementName";
            isElementNameMethod.Parameters.Add(new CodeParameterDeclarationExpression(_string, "elementName"));
            isElementNameMethod.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeBinaryOperatorExpression(
                        new CodeArgumentReferenceExpression("elementName"),
                        CodeBinaryOperatorType.ValueEquality,
                        new CodeFieldReferenceExpression(
                            GlobalSelfReferenceExpression(string.Format("{0}.{1}", element.ActualNamespace, element.Name)),
                            xmlNameField.Name
                            )
                        )
                    )
                );

            // Add GetElementKey method
            CodeMemberMethod getElementKeyMethod = new CodeMemberMethod();

            elementClass.Members.Add(getElementKeyMethod);
            getElementKeyMethod.Comments.Add(DocComment("<summary>"));
            getElementKeyMethod.Comments.Add(DocComment("Gets the element key for the specified configuration element."));
            getElementKeyMethod.Comments.Add(DocComment("</summary>"));
            getElementKeyMethod.Comments.Add(DocComment(string.Format("<param name=\"element\">The <see cref=\"{0}\"/> to return the key for.</param>", configurationElementTypeReference)));
            getElementKeyMethod.Comments.Add(DocComment("<returns>"));
            getElementKeyMethod.Comments.Add(DocComment(string.Format("An <see cref=\"{0}\"/> that acts as the key for the specified <see cref=\"{1}\"/>.", GetTypeReferenceString(typeof(object)), configurationElementTypeReference)));
            getElementKeyMethod.Comments.Add(DocComment("</returns>"));
            getElementKeyMethod.CustomAttributes.Add(_generatedCodeAttribute);
            getElementKeyMethod.Attributes = MemberAttributes.Family | MemberAttributes.Override;
            getElementKeyMethod.ReturnType = _object;
            getElementKeyMethod.Name       = "GetElementKey";
            getElementKeyMethod.Parameters.Add(new CodeParameterDeclarationExpression(GlobalReference(typeof(System.Configuration.ConfigurationElement)), "element"));
            getElementKeyMethod.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeFieldReferenceExpression(
                        new CodeCastExpression(
                            GlobalSelfReference(collectionElement.ItemType.FullName),
                            new CodeArgumentReferenceExpression("element")
                            ),
                        keyProperty.Name
                        )
                    )
                );

            // Add CreateNewElement method
            CodeMemberMethod createNewElementMethod = new CodeMemberMethod();

            elementClass.Members.Add(createNewElementMethod);
            createNewElementMethod.Comments.Add(DocComment("<summary>"));
            createNewElementMethod.Comments.Add(DocComment(string.Format("Creates a new <see cref=\"{0}\"/>.", collectionItemTypeReference)));
            createNewElementMethod.Comments.Add(DocComment("</summary>"));
            createNewElementMethod.Comments.Add(DocComment("<returns>"));
            createNewElementMethod.Comments.Add(DocComment(string.Format("A new <see cref=\"{0}\"/>.", collectionItemTypeReference)));
            createNewElementMethod.Comments.Add(DocComment("</returns>"));
            createNewElementMethod.CustomAttributes.Add(_generatedCodeAttribute);
            createNewElementMethod.Attributes = MemberAttributes.Family | MemberAttributes.Override;
            createNewElementMethod.ReturnType = GlobalReference(typeof(System.Configuration.ConfigurationElement));
            createNewElementMethod.Name       = "CreateNewElement";
            createNewElementMethod.Statements.Add(
                new CodeMethodReturnStatement(new CodeObjectCreateExpression(collectionItemType))
                );

            createNewElementMethod.EndDirectives.Add(EndRegion());

            if ((collectionElement.CodeGenOptions & ConfigurationElementCollectionCodeGenOptions.Indexer) == ConfigurationElementCollectionCodeGenOptions.Indexer)
            {
                // Add indexer for location
                CodeMemberProperty locationIndexerProperty = new CodeMemberProperty();
                elementClass.Members.Add(locationIndexerProperty);
                locationIndexerProperty.StartDirectives.Add(Region("Indexer"));
                locationIndexerProperty.Comments.Add(DocComment("<summary>"));
                locationIndexerProperty.Comments.Add(DocComment(string.Format("Gets the <see cref=\"{0}\"/> at the specified index.", collectionItemTypeReference)));
                locationIndexerProperty.Comments.Add(DocComment("</summary>"));
                locationIndexerProperty.Comments.Add(DocComment(string.Format("<param name=\"index\">The index of the <see cref=\"{0}\"/> to retrieve.</param>", collectionItemTypeReference)));
                locationIndexerProperty.CustomAttributes.Add(_generatedCodeAttribute);
                locationIndexerProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Overloaded;
                locationIndexerProperty.Type       = GlobalSelfReference(collectionElement.ItemType.FullName);
                locationIndexerProperty.Name       = "Item";
                locationIndexerProperty.Parameters.Add(new CodeParameterDeclarationExpression(_int, "index"));
                locationIndexerProperty.HasGet = true;
                locationIndexerProperty.GetStatements.Add(
                    new CodeMethodReturnStatement(
                        new CodeCastExpression(
                            collectionItemType,
                            new CodeMethodInvokeExpression(
                                _base,
                                "BaseGet",
                                new CodeArgumentReferenceExpression("index")
                                )
                            )
                        )
                    );

                // Add GetItemByKey method
                CodeMemberProperty keyIndexerProperty = new CodeMemberProperty();
                elementClass.Members.Add(keyIndexerProperty);
                keyIndexerProperty.Comments.Add(DocComment("<summary>"));
                keyIndexerProperty.Comments.Add(DocComment(string.Format("Gets the <see cref=\"{0}\"/> with the specified key.", collectionItemTypeReference)));
                keyIndexerProperty.Comments.Add(DocComment("</summary>"));
                keyIndexerProperty.Comments.Add(DocComment(string.Format("<param name=\"{0}\">The key of the <see cref=\"{1}\"/> to retrieve.</param>", keyProperty.XmlName, collectionItemTypeReference)));
                keyIndexerProperty.CustomAttributes.Add(_generatedCodeAttribute);
                keyIndexerProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Overloaded;
                keyIndexerProperty.Type       = collectionItemType;
                keyIndexerProperty.Name       = "Item";
                keyIndexerProperty.Parameters.Add(new CodeParameterDeclarationExpression(_object, keyProperty.XmlName));
                keyIndexerProperty.GetStatements.Add(
                    new CodeMethodReturnStatement(
                        new CodeCastExpression(
                            collectionItemType,
                            new CodeMethodInvokeExpression(
                                _base,
                                "BaseGet",
                                new CodeArgumentReferenceExpression(keyProperty.XmlName)
                                )
                            )
                        )
                    );
                keyIndexerProperty.EndDirectives.Add(EndRegion());
            }

            if ((collectionElement.CodeGenOptions & ConfigurationElementCollectionCodeGenOptions.AddMethod) == ConfigurationElementCollectionCodeGenOptions.AddMethod ||
                (collectionElement.CodeGenOptions & ConfigurationElementCollectionCodeGenOptions.ICollection) == ConfigurationElementCollectionCodeGenOptions.ICollection)
            {
                // Add Add method
                CodeMemberMethod addMethod = new CodeMemberMethod();
                elementClass.Members.Add(addMethod);
                addMethod.StartDirectives.Add(Region("Add"));
                addMethod.Comments.Add(DocComment("<summary>"));
                addMethod.Comments.Add(DocComment(string.Format("Adds the specified <see cref=\"{0}\"/> to the <see cref=\"{1}\"/>.", collectionItemTypeReference, configurationElementCollectionTypeReference)));
                addMethod.Comments.Add(DocComment("</summary>"));
                addMethod.Comments.Add(DocComment(string.Format("<param name=\"{0}\">The <see cref=\"{1}\"/> to add.</param>", collectionElement.XmlItemName, collectionItemTypeReference)));
                addMethod.CustomAttributes.Add(_generatedCodeAttribute);
                addMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                addMethod.ReturnType = _void;
                addMethod.Name       = "Add";
                addMethod.Parameters.Add(new CodeParameterDeclarationExpression(GlobalSelfReference(collectionElement.ItemType.FullName), collectionElement.XmlItemName));
                addMethod.Statements.Add(
                    new CodeMethodInvokeExpression(
                        _base,
                        "BaseAdd",
                        new CodeArgumentReferenceExpression(collectionElement.XmlItemName)
                        )
                    );
                addMethod.EndDirectives.Add(EndRegion());
            }

            if ((collectionElement.CodeGenOptions & ConfigurationElementCollectionCodeGenOptions.RemoveMethod) == ConfigurationElementCollectionCodeGenOptions.RemoveMethod ||
                (collectionElement.CodeGenOptions & ConfigurationElementCollectionCodeGenOptions.ICollection) == ConfigurationElementCollectionCodeGenOptions.ICollection)
            {
                // Add Remove method
                CodeMemberMethod removeMethod = new CodeMemberMethod();
                elementClass.Members.Add(removeMethod);
                removeMethod.StartDirectives.Add(Region("Remove"));
                removeMethod.Comments.Add(DocComment("<summary>"));
                removeMethod.Comments.Add(DocComment(string.Format("Removes the specified <see cref=\"{0}\"/> from the <see cref=\"{1}\"/>.", collectionItemTypeReference, configurationElementCollectionTypeReference)));
                removeMethod.Comments.Add(DocComment("</summary>"));
                removeMethod.Comments.Add(DocComment(string.Format("<param name=\"{0}\">The <see cref=\"{1}\"/> to remove.</param>", collectionElement.XmlItemName, collectionItemTypeReference)));
                removeMethod.CustomAttributes.Add(_generatedCodeAttribute);
                removeMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                removeMethod.ReturnType = _void;
                removeMethod.Name       = "Remove";
                removeMethod.Parameters.Add(new CodeParameterDeclarationExpression(collectionItemType, collectionElement.XmlItemName));
                removeMethod.Statements.Add(
                    new CodeMethodInvokeExpression(
                        _base,
                        "BaseRemove",
                        new CodeMethodInvokeExpression(
                            _this,
                            "GetElementKey",
                            new CodeArgumentReferenceExpression(collectionElement.XmlItemName)
                            )
                        )
                    );
                removeMethod.EndDirectives.Add(EndRegion());
            }

            if ((collectionElement.CodeGenOptions & ConfigurationElementCollectionCodeGenOptions.GetItemMethods) == ConfigurationElementCollectionCodeGenOptions.GetItemMethods)
            {
                // Add GetItemAt method
                CodeMemberMethod getItemAtMethod = new CodeMemberMethod();
                elementClass.Members.Add(getItemAtMethod);
                getItemAtMethod.StartDirectives.Add(Region("GetItem"));
                getItemAtMethod.Comments.Add(DocComment("<summary>"));
                getItemAtMethod.Comments.Add(DocComment(string.Format("Gets the <see cref=\"{0}\"/> at the specified index.", collectionItemTypeReference)));
                getItemAtMethod.Comments.Add(DocComment("</summary>"));
                getItemAtMethod.Comments.Add(DocComment(string.Format("<param name=\"index\">The index of the <see cref=\"{0}\"/> to retrieve.</param>", collectionItemTypeReference)));
                getItemAtMethod.CustomAttributes.Add(_generatedCodeAttribute);
                getItemAtMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                getItemAtMethod.ReturnType = collectionItemType;
                getItemAtMethod.Name       = "GetItemAt";
                getItemAtMethod.Parameters.Add(new CodeParameterDeclarationExpression(_int, "index"));
                getItemAtMethod.Statements.Add(
                    new CodeMethodReturnStatement(
                        new CodeCastExpression(
                            collectionItemType,
                            new CodeMethodInvokeExpression(
                                _base,
                                "BaseGet",
                                new CodeArgumentReferenceExpression("index")
                                )
                            )
                        )
                    );

                // Add GetItemByKey method
                CodeMemberMethod getItemByKeyMethod = new CodeMemberMethod();
                elementClass.Members.Add(getItemByKeyMethod);
                getItemByKeyMethod.Comments.Add(DocComment("<summary>"));
                getItemByKeyMethod.Comments.Add(DocComment(string.Format("Gets the <see cref=\"{0}\"/> with the specified key.", collectionItemTypeReference)));
                getItemByKeyMethod.Comments.Add(DocComment("</summary>"));
                getItemByKeyMethod.Comments.Add(DocComment(string.Format("<param name=\"{0}\">The key of the <see cref=\"{1}\"/> to retrieve.</param>", keyProperty.XmlName, collectionItemTypeReference)));
                getItemByKeyMethod.CustomAttributes.Add(_generatedCodeAttribute);
                getItemByKeyMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                getItemByKeyMethod.ReturnType = collectionItemType;
                getItemByKeyMethod.Name       = "GetItemByKey";
                getItemByKeyMethod.Parameters.Add(new CodeParameterDeclarationExpression(GlobalReference(keyProperty.TypeName), keyProperty.XmlName));
                getItemByKeyMethod.Statements.Add(
                    new CodeMethodReturnStatement(
                        new CodeCastExpression(
                            collectionItemType,
                            new CodeMethodInvokeExpression(
                                _base,
                                "BaseGet",
                                new CodeCastExpression(
                                    _object,
                                    new CodeArgumentReferenceExpression(keyProperty.XmlName)
                                    )
                                )
                            )
                        )
                    );
                getItemByKeyMethod.EndDirectives.Add(EndRegion());
            }


            if ((collectionElement.CodeGenOptions & ConfigurationElementCollectionCodeGenOptions.ICollection) == ConfigurationElementCollectionCodeGenOptions.ICollection)
            {
                // Add Clear method
                CodeMemberMethod clearMethod = new CodeMemberMethod();
                elementClass.Members.Add(clearMethod);
                clearMethod.StartDirectives.Add(Region("ICollection"));
                clearMethod.Comments.Add(DocComment("<summary>"));
                clearMethod.Comments.Add(DocComment(string.Format("Removes all items from the <see cref=\"{0}\"/>.", configurationElementCollectionTypeReference)));
                clearMethod.Comments.Add(DocComment("</summary>"));
                clearMethod.CustomAttributes.Add(_generatedCodeAttribute);
                clearMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                clearMethod.ReturnType = _void;
                clearMethod.Name       = "Clear";
                clearMethod.Statements.Add(
                    new CodeMethodInvokeExpression(_base, "BaseClear")
                    );

                //Add Contains method
                CodeMemberMethod containsMethod = new CodeMemberMethod();
                elementClass.Members.Add(containsMethod);
                containsMethod.Comments.Add(DocComment("<summary>"));
                containsMethod.Comments.Add(DocComment(string.Format("Determines whether the <see cref=\"{0}\"/> contains a specific value.", configurationElementCollectionTypeReference)));
                containsMethod.Comments.Add(DocComment("</summary>"));
                containsMethod.Comments.Add(DocComment(string.Format("<param name=\"{0}\">The object to locate in the <see cref=\"{1}\"/>.</param>", collectionElement.XmlItemName, collectionItemTypeReference)));
                containsMethod.CustomAttributes.Add(_generatedCodeAttribute);
                containsMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                containsMethod.ReturnType = _bool;
                containsMethod.Name       = "Contains";
                containsMethod.Parameters.Add(new CodeParameterDeclarationExpression(collectionItemType, collectionElement.XmlItemName));
                containsMethod.Statements.Add(
                    new CodeMethodReturnStatement(
                        new CodeBinaryOperatorExpression(
                            new CodeMethodInvokeExpression(_base, "BaseIndexOf", new CodeArgumentReferenceExpression(collectionElement.XmlItemName)),
                            CodeBinaryOperatorType.GreaterThanOrEqual,
                            new CodePrimitiveExpression(0)
                            )
                        )
                    );

                //Add CopyTo method
                CodeMemberMethod copytoMethod = new CodeMemberMethod();
                elementClass.Members.Add(copytoMethod);
                copytoMethod.Comments.Add(DocComment("<summary>"));
                copytoMethod.Comments.Add(DocComment(string.Format("Copies the elements of the <see cref=\"{0}\"/> to an <see cref=\"System.Array\"/>, starting at a particular <see cref=\"System.Array\"/> index.", configurationElementCollectionTypeReference)));
                copytoMethod.Comments.Add(DocComment("</summary>"));
                copytoMethod.Comments.Add(DocComment(string.Format("<param name=\"array\">The one-dimensional <see cref=\"System.Array\"/> that is the destination of the elements copied from <see cref=\"{0}\"/>. The <see cref=\"System.Array\"/> must have zero-based indexing.</param>", configurationElementCollectionTypeReference)));
                copytoMethod.Comments.Add(DocComment("<param name=\"arrayIndex\">The zero-based index in <paramref name=\"array\"/> at which copying begins.</param>"));
                copytoMethod.CustomAttributes.Add(_generatedCodeAttribute);
                copytoMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                copytoMethod.ReturnType = _void;
                copytoMethod.Name       = "CopyTo";
                copytoMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(collectionItemTypeReference, 1), "array"));
                copytoMethod.Parameters.Add(new CodeParameterDeclarationExpression(_int, "arrayIndex"));
                copytoMethod.Statements.Add(
                    new CodeMethodInvokeExpression(_base, "CopyTo", new CodeArgumentReferenceExpression("array"), new CodeArgumentReferenceExpression("arrayIndex"))
                    );

                //Add ICollection.IsReadOnly property
                CodeMemberProperty isReadOnlyProperty = new CodeMemberProperty();
                elementClass.Members.Add(isReadOnlyProperty);
                isReadOnlyProperty.Comments.Add(DocComment("<summary>"));
                isReadOnlyProperty.Comments.Add(DocComment(string.Format("Gets a value indicating whether the <see cref=\"{0}\"/> is read-only.", configurationElementCollectionTypeReference)));
                isReadOnlyProperty.Comments.Add(DocComment("</summary>"));
                isReadOnlyProperty.CustomAttributes.Add(_generatedCodeAttribute);
                isReadOnlyProperty.Attributes = MemberAttributes.Private;
                isReadOnlyProperty.PrivateImplementationType = icollectionTypeReference;
                isReadOnlyProperty.Type   = _bool;
                isReadOnlyProperty.HasGet = true;
                isReadOnlyProperty.HasSet = false;
                isReadOnlyProperty.Name   = "IsReadOnly";
                isReadOnlyProperty.GetStatements.Add(
                    new CodeMethodReturnStatement(
                        new CodeMethodInvokeExpression(_this, "IsReadOnly")
                        )
                    );

                //Add ICollection.Remove method
                CodeMemberMethod icRemoveMethod = new CodeMemberMethod();
                elementClass.Members.Add(icRemoveMethod);
                icRemoveMethod.Comments.Add(DocComment("<summary>"));
                icRemoveMethod.Comments.Add(DocComment(string.Format("Removes the first occurrence of a specific object from the <see cref=\"{0}\"/>.", configurationElementCollectionTypeReference)));
                icRemoveMethod.Comments.Add(DocComment("</summary>"));
                icRemoveMethod.Comments.Add(DocComment(string.Format("<param name=\"item\">The <see cref=\"{0}\"/> to remove.</param>", collectionItemTypeReference)));
                icRemoveMethod.CustomAttributes.Add(_generatedCodeAttribute);
                icRemoveMethod.Attributes = MemberAttributes.Private;
                icRemoveMethod.PrivateImplementationType = icollectionTypeReference;
                icRemoveMethod.ReturnType = _bool;
                icRemoveMethod.Name       = "Remove";
                icRemoveMethod.Parameters.Add(new CodeParameterDeclarationExpression(collectionItemType, "item"));
                icRemoveMethod.Statements.Add(
                    new CodeVariableDeclarationStatement(_int, "idx",
                                                         new CodeMethodInvokeExpression(_base, "BaseIndexOf", new CodeArgumentReferenceExpression("item"))
                                                         )
                    );
                icRemoveMethod.Statements.Add(
                    new CodeConditionStatement(
                        new CodeBinaryOperatorExpression(
                            new CodeVariableReferenceExpression("idx"),
                            CodeBinaryOperatorType.IdentityEquality,
                            new CodePrimitiveExpression(-1)
                            ),
                        new CodeMethodReturnStatement(new CodePrimitiveExpression(false))
                        )
                    );
                icRemoveMethod.Statements.Add(
                    new CodeMethodInvokeExpression(_base, "BaseRemoveAt", new CodeVariableReferenceExpression("idx"))
                    );
                icRemoveMethod.Statements.Add(
                    new CodeMethodReturnStatement(new CodePrimitiveExpression(true))
                    );

                //Add IEnumerator<> method
                CodeTypeReference ienumTypeReference = new CodeTypeReference(typeof(System.Collections.Generic.IEnumerator <>), CodeTypeReferenceOptions.GlobalReference);
                ienumTypeReference.Options = CodeTypeReferenceOptions.GlobalReference | CodeTypeReferenceOptions.GenericTypeParameter;
                ienumTypeReference.TypeArguments.Add(collectionItemType);
                CodeTypeReference listTypeReference = new CodeTypeReference(typeof(System.Collections.Generic.List <>), CodeTypeReferenceOptions.GlobalReference);
                listTypeReference.Options = CodeTypeReferenceOptions.GlobalReference | CodeTypeReferenceOptions.GenericTypeParameter;
                listTypeReference.TypeArguments.Add(collectionItemType);

                CodeMemberMethod getEnumeratorMethod = new CodeMemberMethod();
                elementClass.Members.Add(getEnumeratorMethod);
                getEnumeratorMethod.Comments.Add(DocComment("<summary>"));
                getEnumeratorMethod.Comments.Add(DocComment("Returns an enumerator that iterates through the collection."));
                getEnumeratorMethod.Comments.Add(DocComment("</summary>"));
                getEnumeratorMethod.CustomAttributes.Add(_generatedCodeAttribute);
                getEnumeratorMethod.Attributes = MemberAttributes.New | MemberAttributes.Public | MemberAttributes.Final;
                getEnumeratorMethod.ReturnType = ienumTypeReference;
                getEnumeratorMethod.Name       = "GetEnumerator";
                getEnumeratorMethod.Statements.Add(
                    new CodeVariableDeclarationStatement(listTypeReference, "list",
                                                         new CodeObjectCreateExpression(listTypeReference, new CodePropertyReferenceExpression(_base, "Count"))
                                                         )
                    );
                CodeVariableReferenceExpression varList = new CodeVariableReferenceExpression("list");
                getEnumeratorMethod.Statements.Add(
                    new CodeVariableDeclarationStatement(GlobalReference(typeof(System.Collections.IEnumerator)), "iter",
                                                         new CodeMethodInvokeExpression(_base, "GetEnumerator")
                                                         )
                    );
                CodeVariableReferenceExpression varIter   = new CodeVariableReferenceExpression("iter");
                CodeExpressionStatement         emptyExpr = new CodeExpressionStatement(new CodeSnippetExpression());
                getEnumeratorMethod.Statements.Add(
                    new CodeIterationStatement(
                        emptyExpr,
                        new CodeMethodInvokeExpression(varIter, "MoveNext"),
                        emptyExpr,
                        new CodeExpressionStatement(
                            new CodeMethodInvokeExpression(
                                varList, "Add",
                                new CodeCastExpression(collectionItemType, new CodePropertyReferenceExpression(varIter, "Current"))
                                )
                            )
                        )
                    );
                getEnumeratorMethod.Statements.Add(
                    new CodeMethodReturnStatement(new CodeMethodInvokeExpression(varList, "GetEnumerator")
                                                  )
                    );
                getEnumeratorMethod.EndDirectives.Add(EndRegion());
            }
        }
Esempio n. 4
0
        private void GenerateProperty(ConfigurationElement element, CodeTypeDeclaration elementClass, ConfigurationProperty property)
        {
            CodeAttributeDeclarationCollection customAttributes = new CodeAttributeDeclarationCollection();

            foreach (Attribute customAttribute in property.Attributes)
            {
                CodeAttributeDeclaration attribute = new CodeAttributeDeclaration(GlobalReference(customAttribute.Name));
                foreach (AttributeParameter parameter in customAttribute.Parameters)
                {
                    if (!string.IsNullOrEmpty(parameter.Name))
                    {
                        attribute.Arguments.Add(
                            new CodeAttributeArgument(parameter.Name, new CodeSnippetExpression(parameter.Value)));
                    }
                    else
                    {
                        attribute.Arguments.Add(new CodeAttributeArgument(new CodeSnippetExpression(parameter.Value)));
                    }
                }
                customAttributes.Add(attribute);
            }

            string xmlPropertyName = string.Format("{0}PropertyName", property.Name);

            // Property's XML name field
            CodeMemberField xmlPropertyNameField = new CodeMemberField(_string, xmlPropertyName);

            elementClass.Members.Add(xmlPropertyNameField);
            xmlPropertyNameField.StartDirectives.Add(Region(string.Format("{0} Property", property.Name)));
            xmlPropertyNameField.Comments.Add(DocComment("<summary>"));
            xmlPropertyNameField.Comments.Add(DocComment(string.Format("The XML name of the <see cref=\"{0}\"/> property.", property.Name)));
            xmlPropertyNameField.Comments.Add(DocComment("</summary>"));
            xmlPropertyNameField.CustomAttributes.Add(_generatedCodeAttribute);
            xmlPropertyNameField.Attributes     = MemberAttributes.Assembly | MemberAttributes.Const;
            xmlPropertyNameField.InitExpression = new CodePrimitiveExpression(property.XmlName);

            // Property's property
            CodeMemberProperty propertyProperty = new CodeMemberProperty();

            elementClass.Members.Add(propertyProperty);

            // Set modifiers, type and name
            propertyProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            propertyProperty.Type       = (property is ElementProperty) ? GlobalSelfReference(property.TypeName) : GlobalReference(property.TypeName);
            propertyProperty.Name       = property.Name;

            propertyProperty.Comments.Add(DocComment("<summary>"));
            propertyProperty.Comments.Add(DocComment(property.DocumentationPropertyText));
            propertyProperty.Comments.Add(DocComment("</summary>"));
            propertyProperty.CustomAttributes.Add(_generatedCodeAttribute);
            propertyProperty.CustomAttributes.AddRange(customAttributes);

            // Add conditional metadata attributes
            if (!string.IsNullOrEmpty(property.DocumentationText))
            {
                propertyProperty.CustomAttributes.Add(new CodeAttributeDeclaration(GlobalReference(typeof(System.ComponentModel.DescriptionAttribute)), new CodeAttributeArgument(new CodePrimitiveExpression(property.DocumentationText))));
            }
            if (!property.Browsable)
            {
                propertyProperty.CustomAttributes.Add(new CodeAttributeDeclaration(GlobalReference(typeof(System.ComponentModel.BrowsableAttribute)), new CodeAttributeArgument(new CodePrimitiveExpression(false))));
            }
            if (property.IsReadOnly)
            {
                propertyProperty.CustomAttributes.Add(new CodeAttributeDeclaration(GlobalReference(typeof(System.ComponentModel.ReadOnlyAttribute)), new CodeAttributeArgument(new CodePrimitiveExpression(true))));
            }
            if (!string.IsNullOrEmpty(property.Category))
            {
                propertyProperty.CustomAttributes.Add(new CodeAttributeDeclaration(GlobalReference(typeof(System.ComponentModel.CategoryAttribute)), new CodeAttributeArgument(new CodePrimitiveExpression(property.Category))));
            }
            if (!string.IsNullOrEmpty(property.DisplayName))
            {
                propertyProperty.CustomAttributes.Add(new CodeAttributeDeclaration(GlobalReference(typeof(System.ComponentModel.DisplayNameAttribute)), new CodeAttributeArgument(new CodePrimitiveExpression(property.DisplayName))));
            }
            if (property is AttributeProperty)
            {
                AttributeProperty attributeProperty = (AttributeProperty)property;
                if (attributeProperty.CustomEditor == CustomEditors.FileNameEditor)
                {
                    propertyProperty.CustomAttributes.Add(
                        new CodeAttributeDeclaration(
                            GlobalReference(typeof(System.ComponentModel.EditorAttribute)),
                            new CodeAttributeArgument(_typeof("System.Windows.Forms.Design.FileNameEditor")),
                            new CodeAttributeArgument(_typeof("System.Drawing.Design.UITypeEditor"))
                            )
                        );
                }
                else if (attributeProperty.CustomEditor == CustomEditors.FolderNameEditor)
                {
                    propertyProperty.CustomAttributes.Add(
                        new CodeAttributeDeclaration(
                            GlobalReference(typeof(System.ComponentModel.EditorAttribute)),
                            new CodeAttributeArgument(_typeof("System.Windows.Forms.Design.FolderNameEditor")),
                            new CodeAttributeArgument(_typeof("System.Drawing.Design.UITypeEditor"))
                            )
                        );
                }
            }

            // Add validator
            if (property.Validator != null)
            {
                GenerateValidator(element, elementClass, propertyProperty, property);
            }

            // Add converter
            if (property.TypeConverter != TypeConverters.None)
            {
                GenerateConverter(propertyProperty, property);
            }

            // Add ConfigurationPropertyAttribute
            CodeAttributeDeclaration configPropertyAttribute = new CodeAttributeDeclaration(GlobalReference(typeof(System.Configuration.ConfigurationPropertyAttribute)),
                                                                                            new CodeAttributeArgument(new CodeFieldReferenceExpression(GlobalSelfReferenceExpression(string.Format("{0}.{1}", element.ActualNamespace, element.Name)), xmlPropertyNameField.Name)),
                                                                                            new CodeAttributeArgument("IsRequired", new CodePrimitiveExpression(property.IsRequired)),
                                                                                            new CodeAttributeArgument("IsKey", new CodePrimitiveExpression(property.IsKey)),
                                                                                            new CodeAttributeArgument("IsDefaultCollection", new CodePrimitiveExpression(property.IsDefaultCollection)));

            if (property is AttributeProperty)
            {
                AttributeProperty attributeProperty = (AttributeProperty)property;
                if (!string.IsNullOrEmpty(attributeProperty.DefaultValue))
                {
                    configPropertyAttribute.Arguments.Add(new CodeAttributeArgument("DefaultValue", new CodeSnippetExpression(attributeProperty.DefaultValue)));
                }
            }
            propertyProperty.CustomAttributes.Add(configPropertyAttribute);

            CodeTypeReference castType;

            if (property is ElementProperty)
            {
                castType = GlobalSelfReference(property.TypeName);
            }
            else
            {
                castType = GlobalReference(property.TypeName);
            }

            // Get method
            propertyProperty.HasGet = true;
            propertyProperty.GetStatements.Add(
                new CodeMethodReturnStatement(
                    new CodeCastExpression(
                        castType,
                        new CodeIndexerExpression(
                            _base,
                            new CodeFieldReferenceExpression(
                                GlobalSelfReferenceExpression(string.Format("{0}.{1}", element.ActualNamespace, element.Name)),
                                xmlPropertyName
                                )
                            )
                        )
                    )
                );

            if (!property.IsReadOnly)
            {
                // Set method
                propertyProperty.HasSet = true;
                propertyProperty.SetStatements.Add(
                    new CodeAssignStatement(
                        new CodeIndexerExpression(
                            _base,
                            new CodeFieldReferenceExpression(
                                GlobalSelfReferenceExpression(string.Format("{0}.{1}", element.ActualNamespace, element.Name)),
                                xmlPropertyName
                                )
                            ),
                        new CodePropertySetValueReferenceExpression()
                        )
                    );
            }

            propertyProperty.EndDirectives.Add(EndRegion());
        }
Esempio n. 5
0
        private void GenerateValidator(ConfigurationElement element, CodeTypeDeclaration elementClass, CodeMemberProperty propertyProperty, ConfigurationProperty property)
        {
            PropertyValidator validator = property.Validator;

            if (validator is CallbackValidator)
            {
                CallbackValidator callbackValidator = validator as CallbackValidator;

                CodeAttributeDeclaration callbackValidatorAttribute = new CodeAttributeDeclaration(GlobalReference(typeof(System.Configuration.CallbackValidatorAttribute)));
                propertyProperty.CustomAttributes.Add(callbackValidatorAttribute);

                string callbackClassName  = string.Format("{0}CallbackValidatorClass", callbackValidator.Name);
                string callbackMethodName = string.Format("{0}Callback", callbackValidator.Callback);
                string FQ = string.Format("{0}.{1}", element.ConfigurationSectionModel.Namespace, callbackClassName);

                callbackValidatorAttribute.Arguments.Add(
                    new CodeAttributeArgument(
                        "Type",
                        new CodeTypeOfExpression(GlobalSelfReference(FQ))
                        )
                    );

                callbackValidatorAttribute.Arguments.Add(
                    new CodeAttributeArgument(
                        "CallbackMethodName",
                        new CodePrimitiveExpression(callbackMethodName)
                        )
                    );
            }
            else if (validator is IntegerValidator)
            {
                IntegerValidator integerValidator = validator as IntegerValidator;

                CodeAttributeDeclaration integerValidatorAttribute = new CodeAttributeDeclaration(GlobalReference(typeof(System.Configuration.IntegerValidatorAttribute)),
                                                                                                  new CodeAttributeArgument("ExcludeRange", new CodePrimitiveExpression(integerValidator.ExcludeRange)),
                                                                                                  new CodeAttributeArgument("MaxValue", new CodePrimitiveExpression(integerValidator.MaxValue)),
                                                                                                  new CodeAttributeArgument("MinValue", new CodePrimitiveExpression(integerValidator.MinValue))
                                                                                                  );
                propertyProperty.CustomAttributes.Add(integerValidatorAttribute);
            }
            else if (validator is LongValidator)
            {
                LongValidator longValidator = validator as LongValidator;

                CodeAttributeDeclaration longValidatorAttribute = new CodeAttributeDeclaration(GlobalReference(typeof(System.Configuration.LongValidatorAttribute)),
                                                                                               new CodeAttributeArgument("ExcludeRange", new CodePrimitiveExpression(longValidator.ExcludeRange)),
                                                                                               new CodeAttributeArgument("MaxValue", new CodePrimitiveExpression(longValidator.MaxValue)),
                                                                                               new CodeAttributeArgument("MinValue", new CodePrimitiveExpression(longValidator.MinValue))
                                                                                               );
                propertyProperty.CustomAttributes.Add(longValidatorAttribute);
            }
            else if (validator is TimeSpanValidator)
            {
                TimeSpanValidator timeSpanValidator = validator as TimeSpanValidator;

                CodeAttributeDeclaration timeSpanValidatorAttribute = new CodeAttributeDeclaration(GlobalReference(typeof(System.Configuration.TimeSpanValidatorAttribute)),
                                                                                                   new CodeAttributeArgument("ExcludeRange", new CodePrimitiveExpression(timeSpanValidator.ExcludeRange)),
                                                                                                   new CodeAttributeArgument("MaxValueString", new CodePrimitiveExpression(timeSpanValidator.MaxValue.ToString())),
                                                                                                   new CodeAttributeArgument("MinValueString", new CodePrimitiveExpression(timeSpanValidator.MinValue.ToString()))
                                                                                                   );
                propertyProperty.CustomAttributes.Add(timeSpanValidatorAttribute);
            }
            else if (validator is PositiveTimeSpanValidator)
            {
                CodeAttributeDeclaration positiveTimeSpanValidatorAttribute = new CodeAttributeDeclaration(GlobalReference(typeof(System.Configuration.PositiveTimeSpanValidatorAttribute)));
                propertyProperty.CustomAttributes.Add(positiveTimeSpanValidatorAttribute);
            }
            else if (validator is RegexStringValidator)
            {
                RegexStringValidator regexStringValidator = validator as RegexStringValidator;

                CodeAttributeDeclaration regexStringValidatorAttribute = new CodeAttributeDeclaration(GlobalReference(typeof(System.Configuration.RegexStringValidatorAttribute)),
                                                                                                      new CodeAttributeArgument(new CodePrimitiveExpression(regexStringValidator.RegularExpression))
                                                                                                      );
                propertyProperty.CustomAttributes.Add(regexStringValidatorAttribute);
            }
            else if (validator is StringValidator)
            {
                StringValidator stringValidator = validator as StringValidator;

                CodeAttributeDeclaration stringValidatorAttribute = new CodeAttributeDeclaration(GlobalReference(typeof(System.Configuration.StringValidatorAttribute)),
                                                                                                 new CodeAttributeArgument("InvalidCharacters", new CodePrimitiveExpression(stringValidator.InvalidCharacters)),
                                                                                                 new CodeAttributeArgument("MaxLength", new CodePrimitiveExpression(stringValidator.MaxLength)),
                                                                                                 new CodeAttributeArgument("MinLength", new CodePrimitiveExpression(stringValidator.MinLength))
                                                                                                 );
                propertyProperty.CustomAttributes.Add(stringValidatorAttribute);
            }
        }
Esempio n. 6
0
        // Checks whether name is a valid variable name. If empty, no check performed.

        /*
         * public static bool IsValidOrEmptyName(string name)
         * {
         *  if (string.IsNullOrEmpty(name))
         *  {
         *      return true;
         *  }
         *  else
         *  {
         *      return (IsValidName(name));
         *  }
         * }
         */

        // Checks whether name is a valid xml name.
        // [20121217] Changing to simple SPACE check for now (most common validation issue). Was causing some issues and I do not have time to resolve yet.

        /*
         * public static bool IsValidXmlName(string name)
         * {
         *  if (!string.IsNullOrEmpty(name) && name.IndexOf(' ') >= 0)
         *  {
         *      return false;
         *  }
         *  else
         *  {
         *      return true;
         *  }
         *
         *  // MATCH:       myName, my0Name, myName0, MyName`
         *  // NOT MATCH:   0myName, my Name
         *  //Regex re = new Regex("^[^0-9\\.][a-zA-Z0-9\\.\\:]+[\\`]?$");
         *  //return re.IsMatch(name);
         * }
         */
        /*
         * public static bool IsValidOrEmptyXmlName(string name)
         * {
         *  if (string.IsNullOrEmpty(name))
         *  {
         *      return true;
         *  }
         *  else
         *  {
         *      return (IsValidXmlName(name));
         *  }
         * }*/

        /// <summary>
        /// Determines whether property should be validated.
        ///
        /// For property model element, parent element is not available. However, we should prevent prop.IsDefaultCollection being set
        /// when parent is not collection. Therefore, we presume that IsDefaultCollection setr to true means parent is collection.
        /// </summary>
        /// <param name="val"></param>
        /// <param name="prop"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        internal static bool RequiresValidation(string val, ConfigurationProperty prop, out NamingHelper.ValidationOptions options)
        {
            return(RequiresValidation(val, prop.IsDefaultCollection, prop, out options));
        }
        private void GenerateConfigurationElementCollectionCode(ConfigurationElement element, CodeTypeDeclaration elementClass)
        {
            ConfigurationElementCollection collectionElement = (ConfigurationElementCollection)element;
            ConfigurationProperty          keyProperty       = collectionElement.ItemType.KeyProperties.Single();

            string xmlPropertyName = string.Format("{0}PropertyName", collectionElement.ItemType.Name);

            string configurationElementTypeReference           = GetTypeReferenceString(typeof(System.Configuration.ConfigurationElement));
            string configurationElementCollectionTypeReference = GetTypeReferenceString(typeof(System.Configuration.ConfigurationElementCollection));

            CodeTypeReference collectionItemType          = GlobalSelfReference(collectionElement.ItemType.FullName);
            string            collectionItemTypeReference = GetTypeSelfReferenceString(collectionElement.ItemType.FullName);

            // Add ConfigurationCollectionAttribute
            CodeAttributeDeclaration collectionType =
                new CodeAttributeDeclaration(
                    GlobalReference(typeof(System.Configuration.ConfigurationCollectionAttribute)),
                    new CodeAttributeArgument(_selftypeof(collectionElement.ItemType.FullName)),
                    new CodeAttributeArgument("CollectionType",
                                              new CodeFieldReferenceExpression(
                                                  GlobalReferenceExpression(collectionElement.CollectionType.GetType()),
                                                  Enum.GetName(collectionElement.CollectionType.GetType(), collectionElement.CollectionType)
                                                  )
                                              )
                    );

            if (collectionElement.CollectionType == System.Configuration.ConfigurationElementCollectionType.BasicMap ||
                collectionElement.CollectionType == System.Configuration.ConfigurationElementCollectionType.BasicMapAlternate)
            {
                collectionType.Arguments.Add(
                    new CodeAttributeArgument("AddItemName",
                                              new CodeFieldReferenceExpression(
                                                  GlobalSelfReferenceExpression(element.FullName),
                                                  xmlPropertyName
                                                  )
                                              )
                    );
            }
            else
            {
                collectionType.Arguments.Add(
                    new CodeAttributeArgument("AddItemName",
                                              new CodePrimitiveExpression(collectionElement.AddItemName)
                                              )
                    );

                collectionType.Arguments.Add(
                    new CodeAttributeArgument("RemoveItemName",
                                              new CodePrimitiveExpression(collectionElement.RemoveItemName)
                                              )
                    );

                collectionType.Arguments.Add(
                    new CodeAttributeArgument("ClearItemsName",
                                              new CodePrimitiveExpression(collectionElement.ClearItemsName)
                                              )
                    );
            }

            elementClass.CustomAttributes.Add(collectionType);

            // Add XmlName field
            CodeMemberField xmlNameField = new CodeMemberField(_string, xmlPropertyName);

            elementClass.Members.Add(xmlNameField);
            xmlNameField.StartDirectives.Add(Region("Constants"));
            xmlNameField.Comments.Add(DocComment("<summary>"));
            xmlNameField.Comments.Add(DocComment(string.Format("The XML name of the individual <see cref=\"{0}\"/> instances in this collection.", collectionItemTypeReference)));
            xmlNameField.Comments.Add(DocComment("</summary>"));
            xmlNameField.CustomAttributes.Add(_generatedCodeAttribute);
            xmlNameField.Attributes     = MemberAttributes.Const | MemberAttributes.Assembly;
            xmlNameField.InitExpression = new CodePrimitiveExpression(collectionElement.XmlItemName);
            xmlNameField.EndDirectives.Add(EndRegion());

            // Add collection type property
            CodeMemberProperty collectionTypeProperty = new CodeMemberProperty();

            elementClass.Members.Add(collectionTypeProperty);
            collectionTypeProperty.StartDirectives.Add(Region("Overrides"));
            collectionTypeProperty.Comments.Add(DocComment("<summary>"));
            collectionTypeProperty.Comments.Add(DocComment(string.Format("Gets the type of the <see cref=\"{0}\"/>.", configurationElementCollectionTypeReference)));
            collectionTypeProperty.Comments.Add(DocComment("</summary>"));
            collectionTypeProperty.Comments.Add(DocComment(string.Format("<returns>The <see cref=\"{0}\"/> of this collection.</returns>", GetTypeReferenceString(typeof(System.Configuration.ConfigurationElementCollectionType)))));
            collectionTypeProperty.CustomAttributes.Add(_generatedCodeAttribute);
            collectionTypeProperty.Attributes = MemberAttributes.Public | MemberAttributes.Override;
            collectionTypeProperty.Type       = GlobalReference(typeof(System.Configuration.ConfigurationElementCollectionType));
            collectionTypeProperty.Name       = "CollectionType";
            collectionTypeProperty.HasGet     = true;
            collectionTypeProperty.GetStatements.Add(
                new CodeMethodReturnStatement(
                    new CodeFieldReferenceExpression(
                        GlobalReferenceExpression(collectionElement.CollectionType.GetType()),
                        Enum.GetName(collectionElement.CollectionType.GetType(), collectionElement.CollectionType)
                        )
                    )
                );

            // Add ElementName property
            CodeMemberProperty elementNameProperty = new CodeMemberProperty();

            elementClass.Members.Add(elementNameProperty);
            elementNameProperty.Comments.Add(DocComment("<summary>"));
            elementNameProperty.Comments.Add(DocComment("Gets the name used to identify this collection of elements"));
            elementNameProperty.Comments.Add(DocComment("</summary>"));
            elementNameProperty.CustomAttributes.Add(_generatedCodeAttribute);
            elementNameProperty.Attributes = MemberAttributes.Family | MemberAttributes.Override;
            elementNameProperty.Type       = _string;
            elementNameProperty.Name       = "ElementName";
            elementNameProperty.HasGet     = true;
            elementNameProperty.GetStatements.Add(
                new CodeMethodReturnStatement(
                    new CodeFieldReferenceExpression(
                        GlobalSelfReferenceExpression(element.FullName),
                        xmlPropertyName
                        )
                    )
                );

            // Add IsElementName method
            CodeMemberMethod isElementNameMethod = new CodeMemberMethod();

            elementClass.Members.Add(isElementNameMethod);
            isElementNameMethod.Comments.Add(DocComment("<summary>"));
            isElementNameMethod.Comments.Add(DocComment(string.Format("Indicates whether the specified <see cref=\"{0}\"/> exists in the <see cref=\"{1}\"/>.", configurationElementTypeReference, configurationElementCollectionTypeReference)));
            isElementNameMethod.Comments.Add(DocComment("</summary>"));
            isElementNameMethod.Comments.Add(DocComment("<param name=\"elementName\">The name of the element to verify.</param>"));
            isElementNameMethod.Comments.Add(DocComment("<returns>"));
            isElementNameMethod.Comments.Add(DocComment("<see langword=\"true\"/> if the element exists in the collection; otherwise, <see langword=\"false\"/>."));
            isElementNameMethod.Comments.Add(DocComment("</returns>"));
            isElementNameMethod.CustomAttributes.Add(_generatedCodeAttribute);
            isElementNameMethod.Attributes = MemberAttributes.Family | MemberAttributes.Override;
            isElementNameMethod.ReturnType = GlobalReference(typeof(bool));
            isElementNameMethod.Name       = "IsElementName";
            isElementNameMethod.Parameters.Add(new CodeParameterDeclarationExpression(_string, "elementName"));
            isElementNameMethod.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeBinaryOperatorExpression(
                        new CodeArgumentReferenceExpression("elementName"),
                        CodeBinaryOperatorType.ValueEquality,
                        new CodeFieldReferenceExpression(
                            GlobalSelfReferenceExpression(string.Format("{0}.{1}", element.ActualNamespace, element.Name)),
                            xmlNameField.Name
                            )
                        )
                    )
                );

            // Add GetElementKey method
            CodeMemberMethod getElementKeyMethod = new CodeMemberMethod();

            elementClass.Members.Add(getElementKeyMethod);
            getElementKeyMethod.Comments.Add(DocComment("<summary>"));
            getElementKeyMethod.Comments.Add(DocComment("Gets the element key for the specified configuration element."));
            getElementKeyMethod.Comments.Add(DocComment("</summary>"));
            getElementKeyMethod.Comments.Add(DocComment(string.Format("<param name=\"element\">The <see cref=\"{0}\"/> to return the key for.</param>", configurationElementTypeReference)));
            getElementKeyMethod.Comments.Add(DocComment("<returns>"));
            getElementKeyMethod.Comments.Add(DocComment(string.Format("An <see cref=\"{0}\"/> that acts as the key for the specified <see cref=\"{1}\"/>.", GetTypeReferenceString(typeof(object)), configurationElementTypeReference)));
            getElementKeyMethod.Comments.Add(DocComment("</returns>"));
            getElementKeyMethod.CustomAttributes.Add(_generatedCodeAttribute);
            getElementKeyMethod.Attributes = MemberAttributes.Family | MemberAttributes.Override;
            getElementKeyMethod.ReturnType = _object;
            getElementKeyMethod.Name       = "GetElementKey";
            getElementKeyMethod.Parameters.Add(new CodeParameterDeclarationExpression(GlobalReference(typeof(System.Configuration.ConfigurationElement)), "element"));
            getElementKeyMethod.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeFieldReferenceExpression(
                        new CodeCastExpression(
                            GlobalSelfReference(collectionElement.ItemType.FullName),
                            new CodeArgumentReferenceExpression("element")
                            ),
                        keyProperty.Name
                        )
                    )
                );

            // Add CreateNewElement method
            CodeMemberMethod createNewElementMethod = new CodeMemberMethod();

            elementClass.Members.Add(createNewElementMethod);
            createNewElementMethod.Comments.Add(DocComment("<summary>"));
            createNewElementMethod.Comments.Add(DocComment(string.Format("Creates a new <see cref=\"{0}\"/>.", collectionItemTypeReference)));
            createNewElementMethod.Comments.Add(DocComment("</summary>"));
            createNewElementMethod.Comments.Add(DocComment("<returns>"));
            createNewElementMethod.Comments.Add(DocComment(string.Format("A new <see cref=\"{0}\"/>.", collectionItemTypeReference)));
            createNewElementMethod.Comments.Add(DocComment("</returns>"));
            createNewElementMethod.CustomAttributes.Add(_generatedCodeAttribute);
            createNewElementMethod.Attributes = MemberAttributes.Family | MemberAttributes.Override;
            createNewElementMethod.ReturnType = GlobalReference(typeof(System.Configuration.ConfigurationElement));
            createNewElementMethod.Name       = "CreateNewElement";
            createNewElementMethod.Statements.Add(
                new CodeMethodReturnStatement(new CodeObjectCreateExpression(collectionItemType))
                );

            createNewElementMethod.EndDirectives.Add(EndRegion());

            if ((collectionElement.CodeGenOptions & ConfigurationElementCollectionCodeGenOptions.Indexer) == ConfigurationElementCollectionCodeGenOptions.Indexer)
            {
                // Add indexer for location
                CodeMemberProperty locationIndexerProperty = new CodeMemberProperty();
                elementClass.Members.Add(locationIndexerProperty);
                locationIndexerProperty.StartDirectives.Add(Region("Indexer"));
                locationIndexerProperty.Comments.Add(DocComment("<summary>"));
                locationIndexerProperty.Comments.Add(DocComment(string.Format("Gets the <see cref=\"{0}\"/> at the specified index.", collectionItemTypeReference)));
                locationIndexerProperty.Comments.Add(DocComment("</summary>"));
                locationIndexerProperty.Comments.Add(DocComment(string.Format("<param name=\"index\">The index of the <see cref=\"{0}\"/> to retrieve.</param>", collectionItemTypeReference)));
                locationIndexerProperty.CustomAttributes.Add(_generatedCodeAttribute);
                locationIndexerProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Overloaded;
                locationIndexerProperty.Type       = GlobalSelfReference(collectionElement.ItemType.FullName);
                locationIndexerProperty.Name       = "Item";
                locationIndexerProperty.Parameters.Add(new CodeParameterDeclarationExpression(_int, "index"));
                locationIndexerProperty.HasGet = true;
                locationIndexerProperty.GetStatements.Add(
                    new CodeMethodReturnStatement(
                        new CodeCastExpression(
                            collectionItemType,
                            new CodeMethodInvokeExpression(
                                _base,
                                "BaseGet",
                                new CodeArgumentReferenceExpression("index")
                                )
                            )
                        )
                    );

                // Add GetItemByKey method
                CodeMemberProperty keyIndexerProperty = new CodeMemberProperty();
                elementClass.Members.Add(keyIndexerProperty);
                keyIndexerProperty.Comments.Add(DocComment("<summary>"));
                keyIndexerProperty.Comments.Add(DocComment(string.Format("Gets the <see cref=\"{0}\"/> with the specified key.", collectionItemTypeReference)));
                keyIndexerProperty.Comments.Add(DocComment("</summary>"));
                keyIndexerProperty.Comments.Add(DocComment(string.Format("<param name=\"{0}\">The key of the <see cref=\"{1}\"/> to retrieve.</param>", keyProperty.XmlName, collectionItemTypeReference)));
                keyIndexerProperty.CustomAttributes.Add(_generatedCodeAttribute);
                keyIndexerProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Overloaded;
                keyIndexerProperty.Type       = collectionItemType;
                keyIndexerProperty.Name       = "Item";
                keyIndexerProperty.Parameters.Add(new CodeParameterDeclarationExpression(_object, keyProperty.XmlName));
                keyIndexerProperty.GetStatements.Add(
                    new CodeMethodReturnStatement(
                        new CodeCastExpression(
                            collectionItemType,
                            new CodeMethodInvokeExpression(
                                _base,
                                "BaseGet",
                                new CodeArgumentReferenceExpression(keyProperty.XmlName)
                                )
                            )
                        )
                    );
                keyIndexerProperty.EndDirectives.Add(EndRegion());
            }

            if ((collectionElement.CodeGenOptions & ConfigurationElementCollectionCodeGenOptions.AddMethod) == ConfigurationElementCollectionCodeGenOptions.AddMethod)
            {
                // Add Add method
                CodeMemberMethod addMethod = new CodeMemberMethod();
                elementClass.Members.Add(addMethod);
                addMethod.StartDirectives.Add(Region("Add"));
                addMethod.Comments.Add(DocComment("<summary>"));
                addMethod.Comments.Add(DocComment(string.Format("Adds the specified <see cref=\"{0}\"/> to the <see cref=\"{1}\"/>.", collectionItemTypeReference, configurationElementCollectionTypeReference)));
                addMethod.Comments.Add(DocComment("</summary>"));
                addMethod.Comments.Add(DocComment(string.Format("<param name=\"{0}\">The <see cref=\"{1}\"/> to add.</param>", collectionElement.XmlItemName, collectionItemTypeReference)));
                addMethod.CustomAttributes.Add(_generatedCodeAttribute);
                addMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                addMethod.ReturnType = _void;
                addMethod.Name       = "Add";
                addMethod.Parameters.Add(new CodeParameterDeclarationExpression(GlobalSelfReference(collectionElement.ItemType.FullName), collectionElement.XmlItemName));
                addMethod.Statements.Add(
                    new CodeMethodInvokeExpression(
                        _base,
                        "BaseAdd",
                        new CodeArgumentReferenceExpression(collectionElement.XmlItemName)
                        )
                    );
                addMethod.EndDirectives.Add(EndRegion());
            }

            if ((collectionElement.CodeGenOptions & ConfigurationElementCollectionCodeGenOptions.RemoveMethod) == ConfigurationElementCollectionCodeGenOptions.RemoveMethod)
            {
                // Add Remove method
                CodeMemberMethod removeMethod = new CodeMemberMethod();
                elementClass.Members.Add(removeMethod);
                removeMethod.StartDirectives.Add(Region("Remove"));
                removeMethod.Comments.Add(DocComment("<summary>"));
                removeMethod.Comments.Add(DocComment(string.Format("Removes the specified <see cref=\"{0}\"/> from the <see cref=\"{1}\"/>.", collectionItemTypeReference, configurationElementCollectionTypeReference)));
                removeMethod.Comments.Add(DocComment("</summary>"));
                removeMethod.Comments.Add(DocComment(string.Format("<param name=\"{0}\">The <see cref=\"{1}\"/> to remove.</param>", collectionElement.XmlItemName, collectionItemTypeReference)));
                removeMethod.CustomAttributes.Add(_generatedCodeAttribute);
                removeMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                removeMethod.ReturnType = _void;
                removeMethod.Name       = "Remove";
                removeMethod.Parameters.Add(new CodeParameterDeclarationExpression(collectionItemType, collectionElement.XmlItemName));
                removeMethod.Statements.Add(
                    new CodeMethodInvokeExpression(
                        _base,
                        "BaseRemove",
                        new CodeMethodInvokeExpression(
                            _this,
                            "GetElementKey",
                            new CodeArgumentReferenceExpression(collectionElement.XmlItemName)
                            )
                        )
                    );
                removeMethod.EndDirectives.Add(EndRegion());
            }

            if ((collectionElement.CodeGenOptions & ConfigurationElementCollectionCodeGenOptions.GetItemMethods) == ConfigurationElementCollectionCodeGenOptions.GetItemMethods)
            {
                // Add GetItemAt method
                CodeMemberMethod getItemAtMethod = new CodeMemberMethod();
                elementClass.Members.Add(getItemAtMethod);
                getItemAtMethod.StartDirectives.Add(Region("GetItem"));
                getItemAtMethod.Comments.Add(DocComment("<summary>"));
                getItemAtMethod.Comments.Add(DocComment(string.Format("Gets the <see cref=\"{0}\"/> at the specified index.", collectionItemTypeReference)));
                getItemAtMethod.Comments.Add(DocComment("</summary>"));
                getItemAtMethod.Comments.Add(DocComment(string.Format("<param name=\"index\">The index of the <see cref=\"{0}\"/> to retrieve.</param>", collectionItemTypeReference)));
                getItemAtMethod.CustomAttributes.Add(_generatedCodeAttribute);
                getItemAtMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                getItemAtMethod.ReturnType = collectionItemType;
                getItemAtMethod.Name       = "GetItemAt";
                getItemAtMethod.Parameters.Add(new CodeParameterDeclarationExpression(_int, "index"));
                getItemAtMethod.Statements.Add(
                    new CodeMethodReturnStatement(
                        new CodeCastExpression(
                            collectionItemType,
                            new CodeMethodInvokeExpression(
                                _base,
                                "BaseGet",
                                new CodeArgumentReferenceExpression("index")
                                )
                            )
                        )
                    );

                // Add GetItemByKey method
                CodeMemberMethod getItemByKeyMethod = new CodeMemberMethod();
                elementClass.Members.Add(getItemByKeyMethod);
                getItemByKeyMethod.Comments.Add(DocComment("<summary>"));
                getItemByKeyMethod.Comments.Add(DocComment(string.Format("Gets the <see cref=\"{0}\"/> with the specified key.", collectionItemTypeReference)));
                getItemByKeyMethod.Comments.Add(DocComment("</summary>"));
                getItemByKeyMethod.Comments.Add(DocComment(string.Format("<param name=\"{0}\">The key of the <see cref=\"{1}\"/> to retrieve.</param>", keyProperty.XmlName, collectionItemTypeReference)));
                getItemByKeyMethod.CustomAttributes.Add(_generatedCodeAttribute);
                getItemByKeyMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                getItemByKeyMethod.ReturnType = collectionItemType;
                getItemByKeyMethod.Name       = "GetItemByKey";
                getItemByKeyMethod.Parameters.Add(new CodeParameterDeclarationExpression(GlobalReference(keyProperty.TypeName), keyProperty.XmlName));
                getItemByKeyMethod.Statements.Add(
                    new CodeMethodReturnStatement(
                        new CodeCastExpression(
                            collectionItemType,
                            new CodeMethodInvokeExpression(
                                _base,
                                "BaseGet",
                                new CodeCastExpression(
                                    _object,
                                    new CodeArgumentReferenceExpression(keyProperty.XmlName)
                                    )
                                )
                            )
                        )
                    );
                getItemByKeyMethod.EndDirectives.Add(EndRegion());
            }
        }