File: AuthoringOM\Compiler\TypeSystem\DesignTimeType.cs
Project: ndp\cdf\src\WF\Common\System.Workflow.ComponentModel.csproj (System.Workflow.ComponentModel)
#pragma warning disable 1634, 1691
namespace System.Workflow.ComponentModel.Compiler
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Globalization;
    using System.Reflection;
    using System.CodeDom;
    using System.Diagnostics;
    using System.Text;
 
    internal sealed class DesignTimeType : Type, ICloneable
    {
        #region Members and Constructors
 
        private static readonly char[] nameSeparators = new char[] { '.', '+' };
        private static readonly char[] elementDecorators = new char[] { '[', '*', '&' };
 
        private Type declaringType;
        private string fullName;
        private TypeAttributes typeAttributes;
        private ITypeProvider typeProvider;
 
        private Attribute[] attributes = null;
        private ConstructorInfo[] constructors = null;
        private FieldInfo[] fields = null;
        private EventInfo[] events = null;
        private PropertyInfo[] properties = null;
        private MethodInfo[] methods = null;
        private Type[] nestedTypes = new Type[0];
        private List<CodeTypeDeclaration> codeDomTypes = null; // accounting for partial types
        private CodeNamespaceImportCollection codeNamespaceImports = null;
        private Guid guid = Guid.Empty;
 
        internal DesignTimeType(Type declaringType,
            string typeName,
            CodeNamespaceImportCollection codeNamespaceImports,
            string namespaceName,
            ITypeProvider typeProvider)
        {
            if (typeName == null)
                throw new ArgumentNullException("typeName");
 
            if (codeNamespaceImports == null)
                throw new ArgumentNullException("codeNamespaceImports");
 
            if (typeProvider == null)
                throw new ArgumentNullException("typeProvider");
 
            if (namespaceName == null && declaringType == null)
                throw new InvalidOperationException(SR.GetString(SR.NamespaceAndDeclaringTypeCannotBeNull));
 
            typeName = Helper.EnsureTypeName(typeName);
            namespaceName = Helper.EnsureTypeName(namespaceName);
 
            if (declaringType == null)
            {
                if (namespaceName.Length == 0)
                    this.fullName = typeName;
                else
                    this.fullName = namespaceName + "." + typeName;
            }
            else
            {
                this.fullName = declaringType.FullName + "+" + typeName;
            }
 
            this.codeDomTypes = new List<CodeTypeDeclaration>();
            this.codeNamespaceImports = codeNamespaceImports;
            this.typeProvider = typeProvider;
            this.declaringType = declaringType;
            this.typeAttributes = default(TypeAttributes);
        }
 
 
        internal DesignTimeType(Type declaringType, string elementTypeFullName, ITypeProvider typeProvider)
        {
            // constructor for declaring types with element (Arrays, Pointers, ByRef). 
            if (typeProvider == null)
                throw new ArgumentNullException("typeProvider");
 
            if (elementTypeFullName.LastIndexOfAny(elementDecorators) == -1)
                throw new ArgumentException(SR.GetString(SR.NotElementType), "elementTypeFullName");
 
            if (elementTypeFullName == null)
                throw new ArgumentNullException("FullName");
 
            this.fullName = Helper.EnsureTypeName(elementTypeFullName);
            this.codeDomTypes = null;
            this.nestedTypes = new Type[0];
            this.codeNamespaceImports = null;
            this.typeProvider = typeProvider;
            this.declaringType = declaringType;
 
            // Set Attributes according to the element type attributes
            Type elementType = GetElementType();
            if (elementType == null)
                throw new ArgumentException(SR.GetString(SR.NotElementType), "elementTypeFullName");
 
            if (IsArray)
            {
                this.typeAttributes = elementType.Attributes & TypeAttributes.VisibilityMask | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Serializable;
            }
            else
            {
                // Pointer/ByRef attributes
                // 
                this.typeAttributes = TypeAttributes.AnsiClass;
            }
        }
 
        #endregion
 
        internal ITypeProvider Provider
        {
            get
            {
                return this.typeProvider;
            }
        }
 
        internal void AddCodeTypeDeclaration(CodeTypeDeclaration codeDomType)
        {
            if (codeDomType == null)
                throw new ArgumentNullException("codeDomType");
 
            //
            this.typeAttributes |= codeDomType.TypeAttributes & ~TypeAttributes.Public;
 
            this.typeAttributes |= Helper.ConvertToTypeAttributes(codeDomType.Attributes, this.declaringType);
            foreach (CodeAttributeDeclaration attribute in codeDomType.CustomAttributes)
            {
                if (string.Equals(attribute.Name, "System.SerializableAttribute", StringComparison.Ordinal) || string.Equals(attribute.Name, "System.Serializable", StringComparison.Ordinal) || string.Equals(attribute.Name, "SerializableAttribute", StringComparison.Ordinal) || string.Equals(attribute.Name, "Serializable", StringComparison.Ordinal))
                {
                    this.typeAttributes |= TypeAttributes.Serializable;
                    break;
                }
            }
            codeDomTypes.Add(codeDomType);
 
            this.attributes = null;
            this.constructors = null;
            this.fields = null;
            this.events = null;
            this.properties = null;
            this.methods = null;
 
            LoadNestedTypes(codeDomType);
        }
 
        #region Properties
        public override Assembly Assembly
        {
            get
            {
                // We can't provide an assembly. This is a design time only type
                return null;
            }
        }
 
        public override string AssemblyQualifiedName
        {
            get
            {
                // We can't provide an assembly. This is a design time only type
                return this.FullName;
            }
        }
 
        public override Type BaseType
        {
            get
            {
                Type type = null;
 
                if (this.codeDomTypes != null)
                {
                    foreach (CodeTypeDeclaration codeDomType in this.codeDomTypes)
                    {
                        // Look for candidates in the type
                        foreach (CodeTypeReference codeBaseType in codeDomType.BaseTypes)
                        {
                            Type typeCandidate = ResolveType(GetTypeNameFromCodeTypeReference(codeBaseType, this));
 
                            if ((typeCandidate != null) && (!typeCandidate.IsInterface))
                            {
                                type = typeCandidate;
                                break;
                            }
                        }
 
                        if (type != null && !type.Equals(ResolveType("System.Object")))
                            break;
                    }
                }
                if (type == null)
                {
                    // Look for implicit base class
                    if (IsArray)
                        type = ResolveType("System.Array");
                    else if (codeDomTypes != null && codeDomTypes.Count > 0)
                    {
                        if (codeDomTypes[0].IsStruct)
                            type = ResolveType("System.ValueType");
                        else if (codeDomTypes[0].IsEnum)
                            type = ResolveType("System.Enum");
                        else if ((codeDomTypes[0].IsClass) && (!IsByRef) && (!IsPointer))
                            type = ResolveType("System.Object");
                        else if (codeDomTypes[0] is CodeTypeDelegate)
                            type = ResolveType("System.Delegate");
                    }
                }
                return type;
            }
        }
 
        public Type GetEnumType()
        {
            if (this.codeDomTypes != null)
            {
                foreach (CodeTypeDeclaration declaration in this.codeDomTypes)
                {
                    Type enumBaseType = declaration.UserData[typeof(Enum)] as Type;
                    if (enumBaseType != null)
                    {
                        return enumBaseType;
                    }
                    else
                    {
                        if (declaration.BaseTypes.Count > 1)
                        {
                            CodeTypeReference reference = declaration.BaseTypes[1]; //the first one would be Enum
                            Type enumBaseType2 = reference.UserData[typeof(Enum)] as Type;
                            if (enumBaseType2 != null)
                                return enumBaseType2;
                        }
                    }
                }
            }
 
            return typeof(int); //default
        }
 
        public override Type DeclaringType
        {
            get
            {
                return this.declaringType;
            }
        }
 
        public override string FullName
        {
            get
            {
                return this.fullName;
            }
        }
 
        public override Guid GUID
        {
            get
            {
                if (this.guid == Guid.Empty)
                    // Set a GUID
                    // 
                    this.guid = Guid.NewGuid();
 
                return this.guid;
            }
        }
 
        public override Module Module
        {
            get
            {
                // We can't provide this. This is a design time only type
                return null;
            }
        }
 
        public override string Name
        {
            get
            {
                string name = this.fullName;
 
                // detect first bracket, any name seperators after it are part of a generic parameter...  
                int idx = name.IndexOf('[');
 
                // Get the name after the last dot
                if (idx != -1)
                    idx = name.Substring(0, idx).LastIndexOfAny(nameSeparators);
                else
                    idx = name.LastIndexOfAny(nameSeparators);
 
                if (idx != -1)
                    name = this.fullName.Substring(idx + 1);
                return name;
            }
        }
 
        public override string Namespace
        {
            get
            {
                if (this.fullName == Name)
                    return string.Empty;
                
                if (this.declaringType != null)
                {
                    return this.declaringType.Namespace;
                }
 
                return this.fullName.Substring(0, this.fullName.Length - Name.Length - 1);
            }
        }
 
        public override RuntimeTypeHandle TypeHandle
        {
            get
            {
                // no runtime context to our type
#pragma warning suppress 56503
                throw new NotImplementedException(TypeSystemSR.GetString("Error_RuntimeNotSupported"));
            }
        }
 
        public override Type UnderlyingSystemType
        {
            get
            {
                return this;
            }
        }
 
 
        #endregion
 
        #region public methods
        public override object[] GetCustomAttributes(bool inherit)
        {
            return GetCustomAttributes(typeof(object), inherit);
        }
 
        public override object[] GetCustomAttributes(Type attributeType, bool inherit)
        {
            if (attributeType == null)
                throw new ArgumentNullException("attributeType");
 
            // Ensure attributes
            if (this.codeDomTypes != null && this.attributes == null)
            {
                CodeAttributeDeclarationCollection attributeDecls = new CodeAttributeDeclarationCollection();
 
                foreach (CodeTypeDeclaration codeType in this.codeDomTypes)
                    attributeDecls.AddRange(codeType.CustomAttributes);
 
                this.attributes = Helper.LoadCustomAttributes(attributeDecls, this);
            }
 
            // It is possible both this.codeDomTypes and this.attributes are null.  
            // For example, when constructing type with element (Array, ByRef, Pointer), we don't
            // set the typedecl because the base type is a system type.  We don't set this.attributes
            // either because we don't actually create a type of the base type.  We simply do
            // new DesignTimeType(null, name, typeProvider).  In such cases, we loose the custom attributes
            // on the base type.
            if (this.attributes != null)
                return Helper.GetCustomAttributes(attributeType, inherit, this.attributes, this);
            else
                return new object[0];
        }
 
        public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
        {
            return GetMembersHelper<ConstructorInfo>(bindingAttr, ref this.constructors, false);
        }
 
        public override EventInfo GetEvent(string name, BindingFlags bindingAttr)
        {
            return GetMemberHelper<EventInfo>(bindingAttr, new MemberSignature(name, null, null), ref this.events);
        }
 
        public override EventInfo[] GetEvents(BindingFlags bindingAttr)
        {
            return GetMembersHelper<EventInfo>(bindingAttr, ref this.events, true);
        }
 
        public override FieldInfo GetField(string name, BindingFlags bindingAttr)
        {
            return GetMemberHelper<FieldInfo>(bindingAttr, new MemberSignature(name, null, null), ref this.fields);
        }
 
        public override FieldInfo[] GetFields(BindingFlags bindingAttr)
        {
            return GetMembersHelper<FieldInfo>(bindingAttr, ref this.fields, true);
        }
 
        public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
        {
            return GetMembersHelper<MethodInfo>(bindingAttr, ref this.methods, true);
        }
 
        public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
        {
            return GetMembersHelper<PropertyInfo>(bindingAttr, ref this.properties, true);
        }
 
        public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr)
        {
            // verify arguments
            VerifyGetMemberArguments(name, bindingAttr);
 
            List<MemberInfo> members = new List<MemberInfo>();
 
            // Methods
            if ((type & MemberTypes.Method) != 0)
                members.AddRange(GetMembersHelper<MethodInfo>(bindingAttr, new MemberSignature(name, null, null), ref this.methods));
 
            // Constructors
            if ((type & MemberTypes.Constructor) != 0)
                members.AddRange(GetMembersHelper<ConstructorInfo>(bindingAttr, new MemberSignature(name, null, null), ref this.constructors));
 
            // Properties
            if ((type & MemberTypes.Property) != 0)
                members.AddRange(GetMembersHelper<PropertyInfo>(bindingAttr, new MemberSignature(name, null, null), ref this.properties));
 
            // Events
            if ((type & MemberTypes.Event) != 0)
                members.AddRange(GetMembersHelper<EventInfo>(bindingAttr, new MemberSignature(name, null, null), ref this.events));
 
            // Fields
            if ((type & MemberTypes.Field) != 0)
                members.AddRange(GetMembersHelper<FieldInfo>(bindingAttr, new MemberSignature(name, null, null), ref this.fields));
 
            // Nested types
            if ((type & MemberTypes.NestedType) != 0)
                members.AddRange(GetMembersHelper<Type>(bindingAttr, new MemberSignature(name, null, null), ref this.nestedTypes));
 
            return members.ToArray();
        }
 
        public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
        {
            // verify arguments
            VerifyGetMemberArguments(bindingAttr);
 
            ArrayList members = new ArrayList();
 
            // 
            members.AddRange(GetMethods(bindingAttr));
            members.AddRange(GetProperties(bindingAttr));
            members.AddRange(GetEvents(bindingAttr));
            members.AddRange(GetFields(bindingAttr));
            members.AddRange(GetNestedTypes(bindingAttr));
 
            return (MemberInfo[])members.ToArray(typeof(MemberInfo));
        }
 
        public override MemberInfo[] GetDefaultMembers()
        {
            // Get all of the custom attributes
            DefaultMemberAttribute attr = null;
 
            for (Type t = this; t != null; t = t.BaseType)
            {
                object[] attrs = GetCustomAttributes(typeof(DefaultMemberAttribute), false);
                if (attrs != null && attrs.Length > 0)
                    attr = attrs[0] as DefaultMemberAttribute;
 
                if (attr != null)
                    break;
            }
 
            if (attr == null)
                return new MemberInfo[0];
 
            String defaultMember = attr.MemberName;
            MemberInfo[] members = GetMember(defaultMember);
            if (members == null)
                members = new MemberInfo[0];
            return members;
        }
 
        public override Type GetNestedType(string name, BindingFlags bindingAttr)
        {
            return GetMemberHelper<Type>(bindingAttr, new MemberSignature(name, null, null), ref this.nestedTypes);
        }
 
        public override Type[] GetNestedTypes(BindingFlags bindingAttr)
        {
            return GetMembersHelper<Type>(bindingAttr, ref this.nestedTypes, false);
        }
 
        public override Type GetInterface(string name, bool ignoreCase)
        {
            if (this.codeDomTypes != null)
            {
                StringComparison compare = (ignoreCase) ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
 
                // search in the type
                foreach (CodeTypeDeclaration codeDomType in this.codeDomTypes)
                {
                    foreach (CodeTypeReference codeBaseType in codeDomType.BaseTypes)
                    {
                        Type interfaceCandidate = ResolveType(GetTypeNameFromCodeTypeReference(codeBaseType, this));
 
                        if (interfaceCandidate != null)
                        {
                            if ((interfaceCandidate.IsInterface == true) && (string.Equals(interfaceCandidate.FullName, name, compare)))
                                return interfaceCandidate;
 
                            // look in base class/intefaces
                            Type baseInterfaceCandidate = interfaceCandidate.GetInterface(name, ignoreCase);
 
                            if (baseInterfaceCandidate != null)
                                return baseInterfaceCandidate;
                        }
                    }
                }
            }
 
            return null;
        }
 
        public override Type[] GetInterfaces()
        {
            ArrayList types = new ArrayList();
 
            if (this.codeDomTypes != null)
            {
                // search in the type
                foreach (CodeTypeDeclaration codeDomType in this.codeDomTypes)
                {
                    foreach (CodeTypeReference codeBaseType in codeDomType.BaseTypes)
                    {
                        Type interfaceCandidate = ResolveType(GetTypeNameFromCodeTypeReference(codeBaseType, this));
 
                        if (interfaceCandidate != null)
                        {
                            if ((interfaceCandidate.IsInterface == true) && (!types.Contains(interfaceCandidate)))
                                types.Add(interfaceCandidate);
 
                            // look in base class/intefaces
                            Type[] baseInterfaces = interfaceCandidate.GetInterfaces();
 
                            foreach (Type baseInterfaceCandidate in baseInterfaces)
                            {
                                if ((baseInterfaceCandidate != null) && (!types.Contains(baseInterfaceCandidate)))
                                    types.Add(baseInterfaceCandidate);
                            }
                        }
                    }
                }
            }
 
            return (Type[])types.ToArray(typeof(Type));
        }
 
        public override object InvokeMember(string name, BindingFlags bindingFlags, Binder binder, object target, object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParams)
        {
            throw new NotImplementedException(TypeSystemSR.GetString("Error_RuntimeNotSupported"));
        }
 
        public override string ToString()
        {
            return fullName;
        }
 
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
 
        public override bool IsDefined(Type attributeType, bool inherit)
        {
            if (attributeType == null)
                throw new ArgumentNullException("attributeType");
 
            // 
            this.GetCustomAttributes(true);
 
            if (Helper.IsDefined(attributeType, inherit, attributes, this))
                return true;
 
            return false;
        }
 
        public override Type GetElementType()
        {
            Type elementType = null;
            int elementCharPosition = fullName.LastIndexOfAny(elementDecorators);
 
            if (elementCharPosition >= 0)
                elementType = ResolveType(fullName.Substring(0, elementCharPosition));
 
            return elementType;
        }
 
 
        public override int GetArrayRank()
        {
            if (!IsArray)
                throw new ArgumentException(TypeSystemSR.GetString("Error_TypeIsNotArray"));
 
            int position = Name.LastIndexOf('[');
            int rank = 1;
            while (Name[position] != ']')
            {
                if (Name[position] == ',')
                    rank++;
                position++;
            }
 
            return rank;
        }
 
        public override bool IsAssignableFrom(Type c)
        {
            return TypeProvider.IsAssignable(this, c);
        }
 
        public override bool IsSubclassOf(Type c)
        {
            if (c == null)
                return false;
 
            return TypeProvider.IsSubclassOf(this, c);
        }
 
        public override Type MakeArrayType()
        {
            return this.typeProvider.GetType(String.Format(CultureInfo.InvariantCulture, "{0}[]", this.FullName));
        }
 
        #endregion
 
        #region Helpers
 
        private void VerifyGetMemberArguments(string name, BindingFlags bindingAttr)
        {
            if (name == null)
                throw new ArgumentNullException("name");
 
            VerifyGetMemberArguments(bindingAttr);
        }
 
        private void VerifyGetMemberArguments(BindingFlags bindingAttr)
        {
            // We only support public based constructors on DesignTime type
            BindingFlags supported = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.IgnoreCase;
 
            if ((bindingAttr & ~supported) != 0)
                throw new ArgumentException(TypeSystemSR.GetString("Error_GetMemberBindingOptions"));
 
        }
        internal Type ResolveType(string name)
        {
            Type type = null;
 
            //first assume full name was provided
            type = typeProvider.GetType(name);
 
            if (type == null && !string.IsNullOrEmpty(Namespace))
                // prefixing the namespace
                type = typeProvider.GetType(Namespace + "." + name);
 
            // maybe it is nested type on the current type
            if (type == null)
                type = typeProvider.GetType(fullName + "+" + name);
 
            // prefixing imported namespaces
            if ((type == null) && (this.codeNamespaceImports != null))
            {
                foreach (CodeNamespaceImport codeNamespaceImport in this.codeNamespaceImports)
                {
                    type = typeProvider.GetType(codeNamespaceImport.Namespace + "." + name);
                    if (type != null)
                        break;
                }
            }
 
            // maybe it is a fullname of a nested class
            if (type == null)
            {
                string nestedName = name;
                int indexOfFirstDot = name.IndexOf('.');
                int indexOfLastDot = -1;
                while (((indexOfLastDot = nestedName.LastIndexOf('.')) != indexOfFirstDot) && (type == null))
                {
                    nestedName = nestedName.Substring(0, indexOfLastDot) + "+" + nestedName.Substring(indexOfLastDot + 1);
                    type = typeProvider.GetType(nestedName);
                }
            }
 
            // 
            return type;
        }
 
        private bool FilterMember(MemberInfo memberInfo, BindingFlags bindingFlags)
        {
            bool isPublic = false;
            bool isStatic = false;
 
            if (this.IsInterface)
            {
                isPublic = true;
                isStatic = false;
            }
            else if (memberInfo is MethodBase)
            {
                isPublic = (memberInfo as MethodBase).IsPublic;
                isStatic = (memberInfo as MethodBase).IsStatic;
            }
            else if (memberInfo is DesignTimeEventInfo)
            {
                isPublic = (memberInfo as DesignTimeEventInfo).IsPublic;
                isStatic = (memberInfo as DesignTimeEventInfo).IsStatic;
            }
            else if (memberInfo is FieldInfo)
            {
                isPublic = (memberInfo as FieldInfo).IsPublic;
                isStatic = (memberInfo as FieldInfo).IsStatic;
            }
            else if (memberInfo is PropertyInfo)
            {
                // Property public\static attributes can be fetched using the accessors 
                PropertyInfo propertyInfo = memberInfo as PropertyInfo;
                MethodInfo accessorMethod = null;
                if (propertyInfo.CanRead)
                    accessorMethod = propertyInfo.GetGetMethod(true);
                else
                    accessorMethod = propertyInfo.GetSetMethod(true);
                if (accessorMethod != null)
                {
                    isPublic = accessorMethod.IsPublic;
                    isStatic = accessorMethod.IsStatic;
                }
            }
            else if (memberInfo is Type)
            {
                isPublic = (memberInfo as Type).IsPublic || (memberInfo as Type).IsNestedPublic;
                // No static check.
                return ((((isPublic) && ((bindingFlags & BindingFlags.Public) != 0)) || ((!isPublic) && ((bindingFlags & BindingFlags.NonPublic) != 0))));
            }
 
            return ((((isPublic) && ((bindingFlags & BindingFlags.Public) != 0)) || ((!isPublic) && ((bindingFlags & BindingFlags.NonPublic) != 0))) && (((isStatic) && ((bindingFlags & BindingFlags.Static) != 0)) || ((!isStatic) && ((bindingFlags & BindingFlags.Instance) != 0))));
        }
 
        // generic method that implements all GetXXXs methods
        private T[] GetMembersHelper<T>(BindingFlags bindingAttr, ref T[] members, bool searchBase)
            where T : MemberInfo
        {
            // verify arguments
            VerifyGetMemberArguments(bindingAttr);
 
            EnsureMembers(typeof(T));
 
            Dictionary<MemberSignature, T> membersDictionary = new Dictionary<MemberSignature, T>();
 
            // get local properties
            foreach (T memberInfo in members)
            {
                MemberSignature memberSignature = new MemberSignature(memberInfo);
 
                if ((FilterMember(memberInfo, bindingAttr)) && (!membersDictionary.ContainsKey(memberSignature)))
                    membersDictionary.Add(new MemberSignature(memberInfo), memberInfo);
            }
 
            if (searchBase && (bindingAttr & BindingFlags.DeclaredOnly) == 0)
            {
                // FlattenHierarchy is required to return static members from base classes.
                if ((bindingAttr & BindingFlags.FlattenHierarchy) == 0)
                    bindingAttr &= ~BindingFlags.Static;
 
                Type baseType = BaseType;
                if (baseType != null)
                {
                    T[] baseMembers = GetBaseMembers(typeof(T), baseType, bindingAttr) as T[];
 
                    foreach (T memberInfo in baseMembers)
                    {
                        // We should not return private members from base classes. Note: Generics requires us to use "as".
                        if ((memberInfo is FieldInfo && (memberInfo as FieldInfo).IsPrivate) || (memberInfo is MethodBase && (memberInfo as MethodBase).IsPrivate) || (memberInfo is Type && (memberInfo as Type).IsNestedPrivate))
                            continue;
 
                        // verify a member with this signature was not already created
                        MemberSignature memberSignature = new MemberSignature(memberInfo);
 
                        if (!membersDictionary.ContainsKey(memberSignature))
                            membersDictionary.Add(memberSignature, memberInfo);
                    }
                }
            }
 
            List<T> memberCollection = new List<T>(membersDictionary.Values);
            return memberCollection.ToArray();
        }
 
        private MemberInfo[] GetBaseMembers(Type type, Type baseType, BindingFlags bindingAttr)
        {
            MemberInfo[] members = null;
            if (type == typeof(PropertyInfo))
                members = baseType.GetProperties(bindingAttr);
            else if (type == typeof(EventInfo))
                members = baseType.GetEvents(bindingAttr);
            else if (type == typeof(ConstructorInfo))
                members = baseType.GetConstructors(bindingAttr);
            else if (type == typeof(MethodInfo))
                members = baseType.GetMethods(bindingAttr);
            else if (type == typeof(FieldInfo))
                members = baseType.GetFields(bindingAttr);
            else if (type == typeof(Type))
                members = baseType.GetNestedTypes(bindingAttr);
 
            return members;
        }
 
        private T[] GetMembersHelper<T>(BindingFlags bindingAttr, MemberSignature memberSignature, ref T[] members)
            where T : MemberInfo
        {
            List<T> memberCandidates = new List<T>();
            foreach (T memberInfo in this.GetMembersHelper<T>(bindingAttr, ref members, true))
            {
                MemberSignature candididateMemberSignature = new MemberSignature(memberInfo);
                if (candididateMemberSignature.FilterSignature(memberSignature))
                    memberCandidates.Add(memberInfo);
            }
            return memberCandidates.ToArray();
        }
 
        // generic method that implements all GetXXX methods
        private T GetMemberHelper<T>(BindingFlags bindingAttr, MemberSignature memberSignature, ref T[] members)
            where T : MemberInfo
        {
            // verify arguments
            VerifyGetMemberArguments(bindingAttr);
 
            EnsureMembers(typeof(T));
 
            // search the local type
            foreach (T memberInfo in members)
            {
                MemberSignature candididateMemberSignature = new MemberSignature(memberInfo);
                if (candididateMemberSignature.FilterSignature(memberSignature) && FilterMember(memberInfo, bindingAttr))
                    return memberInfo;
            }
 
            if ((bindingAttr & BindingFlags.DeclaredOnly) == 0)
            {
                // serach base types
 
                // FlattenHierarchy is required to return static members from base classes.
                if ((bindingAttr & BindingFlags.FlattenHierarchy) == 0)
                    bindingAttr &= ~BindingFlags.Static;
 
                Type baseType = BaseType;
                if (baseType != null)
                {
                    T memberInfo = (T)GetBaseMember(typeof(T), baseType, bindingAttr, memberSignature);
 
                    if (memberInfo != null)
                    {
                        // We should not return private members from base classes. Note: Generics requires us to use "as".
                        if ((memberInfo is FieldInfo && (memberInfo as FieldInfo).IsPrivate) || (memberInfo is MethodBase && (memberInfo as MethodBase).IsPrivate) || (memberInfo is Type && (memberInfo as Type).IsNestedPrivate))
                            return null;
 
                        return memberInfo;
                    }
                }
            }
 
            return null;
        }
 
        internal MemberInfo GetBaseMember(Type type, Type baseType, BindingFlags bindingAttr, MemberSignature memberSignature)
        {
            if (memberSignature == null)
                throw new ArgumentNullException("memberSignature");
 
            if (baseType == null)
                return null;
 
            MemberInfo member = null;
 
            if (typeof(PropertyInfo).IsAssignableFrom(type))
            {
                if (memberSignature.Parameters != null)
                    member = baseType.GetProperty(memberSignature.Name, bindingAttr, null, memberSignature.ReturnType, memberSignature.Parameters, null);
                else
                    member = baseType.GetProperty(memberSignature.Name, bindingAttr);
            }
            else if (typeof(EventInfo).IsAssignableFrom(type))
                member = baseType.GetEvent(memberSignature.Name, bindingAttr);
            else if (typeof(ConstructorInfo).IsAssignableFrom(type))
                member = baseType.GetConstructor(bindingAttr, null, memberSignature.Parameters, null);
            else if (typeof(MethodInfo).IsAssignableFrom(type))
            {
                if (memberSignature.Parameters != null)
                    member = baseType.GetMethod(memberSignature.Name, bindingAttr, null, memberSignature.Parameters, null);
                else
                    member = baseType.GetMethod(memberSignature.Name, bindingAttr);
            }
            else if (typeof(FieldInfo).IsAssignableFrom(type))
                member = baseType.GetField(memberSignature.Name, bindingAttr);
            else if (typeof(Type).IsAssignableFrom(type))
                member = baseType.GetNestedType(memberSignature.Name, bindingAttr);
 
            return member;
        }
 
        internal static string GetTypeNameFromCodeTypeReference(CodeTypeReference codeTypeReference, DesignTimeType declaringType)
        {
            StringBuilder typeName = new StringBuilder();
 
            if (codeTypeReference.ArrayRank == 0)
            {
                Type resolvedType = null;
                if (declaringType != null)
                    resolvedType = declaringType.ResolveType(codeTypeReference.BaseType);
                if (resolvedType != null)
                    typeName.Append(resolvedType.FullName);
                else
                    typeName.Append(codeTypeReference.BaseType);
 
                if ((codeTypeReference.TypeArguments != null) && (codeTypeReference.TypeArguments.Count > 0))
                {
                    if (codeTypeReference.BaseType.IndexOf('`') == -1)
                        typeName.Append(string.Format(CultureInfo.InvariantCulture, "`{0}", new object[] { codeTypeReference.TypeArguments.Count }));
                    typeName.Append("[");
                    foreach (CodeTypeReference typeArgument in codeTypeReference.TypeArguments)
                    {
                        typeName.Append("[");
                        typeName.Append(GetTypeNameFromCodeTypeReference(typeArgument, declaringType));
                        typeName.Append("],");
                    }
                    typeName.Length = typeName.Length - 1; //remove the last comma
                    typeName.Append("]");
                }
            }
            else
            {
                typeName.Append(GetTypeNameFromCodeTypeReference(codeTypeReference.ArrayElementType, declaringType));
 
                // Build array decoration (ByRefs and Pointers are part of the the BaseType) 
                typeName.Append("[");
                for (int loop = 0; loop < codeTypeReference.ArrayRank - 1; loop++)
                    typeName.Append(',');
 
                typeName.Append("]");
            }
 
            return typeName.ToString();
        }
 
        #endregion
 
        #region implementation overrides
 
        protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
        {
            return GetMemberHelper<ConstructorInfo>(bindingAttr, new MemberSignature(null, types, null), ref this.constructors);
        }
 
        protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
        {
            return GetMemberHelper<MethodInfo>(bindingAttr, new MemberSignature(name, types, null), ref this.methods);
        }
 
        protected override PropertyInfo GetPropertyImpl(String name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
        {
            return GetMemberHelper<PropertyInfo>(bindingAttr, new MemberSignature(name, types, null), ref this.properties);
        }
 
        protected override TypeAttributes GetAttributeFlagsImpl()
        {
            return typeAttributes;
        }
 
        protected override bool HasElementTypeImpl()
        {
 
            int elementCharPosition = Name.LastIndexOfAny(elementDecorators);
            return (elementCharPosition != -1);
        }
 
        protected override bool IsArrayImpl()
        {
            int elementCharPosition = Name.LastIndexOfAny(elementDecorators);
            if ((elementCharPosition != -1) && (Name[elementCharPosition] == '['))
                return true;
 
            return false;
 
        }
 
        protected override bool IsByRefImpl()
        {
            return (this.fullName[this.fullName.Length - 1] == '&');
        }
 
        public override Type MakeByRefType()
        {
            return this.ResolveType(this.fullName + "&");
        }
 
 
        protected override bool IsCOMObjectImpl()
        {
            //
            return false;
        }
 
        protected override bool IsContextfulImpl()
        {
            //
            return false;
        }
 
        protected override bool IsMarshalByRefImpl()
        {
            //
            return false;
        }
 
        protected override bool IsPointerImpl()
        {
            return (this.fullName[this.fullName.Length - 1] == '*');
        }
 
        protected override bool IsPrimitiveImpl()
        {
            return false;
        }
 
        #endregion
 
        #region Loaders
 
        private void EnsureMembers(Type type)
        {
            if ((type == typeof(PropertyInfo)) && (this.properties == null))
                this.properties = GetCodeDomMembers<PropertyInfo>().ToArray();
            else if ((type == typeof(FieldInfo)) && (this.fields == null))
                this.fields = GetCodeDomMembers<FieldInfo>().ToArray();
            else if ((type == typeof(ConstructorInfo)) && (this.constructors == null))
                this.constructors = GetCodeDomConstructors().ToArray();
            else if ((type == typeof(EventInfo)) && (this.events == null))
                this.events = GetCodeDomMembers<EventInfo>().ToArray();
            else if ((type == typeof(MethodInfo)) && (this.methods == null))
            {
                EnsureMembers(typeof(PropertyInfo));
                EnsureMembers(typeof(EventInfo));
 
                List<MethodInfo> methodCollection = GetCodeDomMembers<MethodInfo>();
                MethodInfo methodInfo = null;
 
                foreach (PropertyInfo propertyInfo in this.properties)
                {
                    if ((methodInfo = propertyInfo.GetGetMethod()) != null)
                        methodCollection.Add(methodInfo);
 
                    if ((methodInfo = propertyInfo.GetSetMethod()) != null)
                        methodCollection.Add(methodInfo);
                }
 
                foreach (EventInfo eventInfo in this.events)
                {
                    if ((methodInfo = eventInfo.GetAddMethod()) != null)
                        methodCollection.Add(methodInfo);
 
                    if ((methodInfo = eventInfo.GetRemoveMethod()) != null)
                        methodCollection.Add(methodInfo);
 
                    if ((methodInfo = eventInfo.GetRaiseMethod()) != null)
                        methodCollection.Add(methodInfo);
                }
 
                this.methods = methodCollection.ToArray();
            }
        }
 
        private List<T> GetCodeDomMembers<T>()
            where T : MemberInfo
        {
            List<T> memberCollection = new List<T>();
 
            if (this.codeDomTypes != null)
            {
                foreach (CodeTypeDeclaration codeDomType in codeDomTypes)
                {
                    //!!! Work around for supporting delegates
                    if (codeDomType is CodeTypeDelegate && typeof(T) == typeof(MethodInfo))
                    {
                        CodeMemberMethod invokeMethod = new CodeMemberMethod();
                        invokeMethod.Name = "Invoke";
                        invokeMethod.Attributes = MemberAttributes.Public;
                        foreach (CodeParameterDeclarationExpression parameterDecl in ((CodeTypeDelegate)codeDomType).Parameters)
                            invokeMethod.Parameters.Add(parameterDecl);
                        invokeMethod.ReturnType = ((CodeTypeDelegate)codeDomType).ReturnType;
                        memberCollection.Add((T)CreateMemberInfo(typeof(MethodInfo), invokeMethod));
                    }
 
                    foreach (CodeTypeMember member in codeDomType.Members)
                    {
                        T memberInfo = (T)CreateMemberInfo(typeof(T), member);
 
                        if (memberInfo != null)
                            memberCollection.Add(memberInfo);
                    }
                }
            }
            return memberCollection;
        }
 
        // CFx bug 461 
        // The code dom being generated by VsCodeDomParser.cs does not
        // add default constructors for classes unless they
        // exist in the source code. Unfortunately, this cannot be easily
        // fixed in the CodeDomParser because the code dom returned by that
        // class is expected to kept in sync with the real source code. 
        // So we cannot "fabricate" a default constructor there without
        // breaking lots of assumptions elsewhere in the code. 
        // Instead, we add a default constructor here, if necessary.
        private List<ConstructorInfo> GetCodeDomConstructors()
        {
            List<ConstructorInfo> constructors = GetCodeDomMembers<ConstructorInfo>();
            // we only add a default constructor if 
            // this is a struct or is a non-static\non-abstract class and it doesn't have any 
            // constructors
            //  * Note - static classes are represented as Abstract and Sealed
            //           abstract classes are represented as Abstract; thus we will check just for that flag
            if (this.IsValueType || ((constructors.Count == 0) && !this.IsAbstract))
            {
                CodeConstructor codeConstructor = new CodeConstructor();
                codeConstructor.Attributes = MemberAttributes.Public;
                ConstructorInfo constructorInfo = new DesignTimeConstructorInfo(this, codeConstructor);
                constructors.Add(constructorInfo);
            }
            return constructors;
        }
 
        private void LoadNestedTypes(CodeTypeDeclaration codeDomType)
        {
            List<Type> localMembers = new List<Type>();
 
            foreach (Type t in this.nestedTypes)
                localMembers.Add(t);
 
            foreach (CodeTypeMember member in codeDomType.Members)
            {
                if (!(member is CodeTypeDeclaration))
                    continue;
 
                CodeTypeDeclaration codeType = member as CodeTypeDeclaration;
                Type partialType = null;
                foreach (Type nestedType in localMembers)
                {
                    if (nestedType.Name.Equals(Helper.EnsureTypeName(codeType.Name)))
                    {
                        partialType = nestedType;
                        break;
                    }
                }
                if (partialType == null)
                {
                    partialType = new DesignTimeType(this, codeType.Name, this.codeNamespaceImports, this.fullName, this.typeProvider);
                    localMembers.Add(partialType);
                    ((TypeProvider)this.typeProvider).AddType(partialType);
                }
                ((DesignTimeType)partialType).AddCodeTypeDeclaration(codeType);
            }
            this.nestedTypes = localMembers.ToArray();
        }
 
        private MemberInfo CreateMemberInfo(Type memberInfoType, CodeTypeMember member)
        {
            MemberInfo memberInfo = null;
 
            if ((memberInfoType == typeof(PropertyInfo)) && (member is CodeMemberProperty))
                memberInfo = new DesignTimePropertyInfo(this, member as CodeMemberProperty);
            else if ((memberInfoType == typeof(EventInfo)) && (member is CodeMemberEvent))
                memberInfo = new DesignTimeEventInfo(this, member as CodeMemberEvent);
            else if ((memberInfoType == typeof(FieldInfo)) && (member is CodeMemberField))
                memberInfo = new DesignTimeFieldInfo(this, member as CodeMemberField);
            else if ((memberInfoType == typeof(ConstructorInfo)) && ((member is CodeConstructor) || (member is CodeTypeConstructor)))
                memberInfo = new DesignTimeConstructorInfo(this, member as CodeMemberMethod);
            else if ((memberInfoType == typeof(MethodInfo)) && (member.GetType() == typeof(CodeMemberMethod)))
                memberInfo = new DesignTimeMethodInfo(this, member as CodeMemberMethod);
            return memberInfo;
        }
 
        #endregion
 
        #region MemberSignature class
        // Uniquely identify a memberInfo
        internal class MemberSignature
        {
            #region Members and Constructors
 
            private string name = null;
            private Type[] parameters = null;
            private Type returnType = null;
            readonly int hashCode;
 
            internal MemberSignature(MemberInfo memberInfo)
            {
                this.name = memberInfo.Name;
 
                if (memberInfo is MethodBase)
                {
                    List<Type> typeCollection = new List<Type>();
 
                    // method/constructor arguments
                    foreach (ParameterInfo parameterInfo in (memberInfo as MethodBase).GetParameters())
                        typeCollection.Add(parameterInfo.ParameterType);
 
                    this.parameters = typeCollection.ToArray();
 
                    if (memberInfo is MethodInfo)
                        this.returnType = ((MethodInfo)memberInfo).ReturnType;
                }
                else if (memberInfo is PropertyInfo)
                {
                    PropertyInfo propertyInfo = memberInfo as PropertyInfo;
                    List<Type> typeCollection = new List<Type>();
 
                    // indexer arguments
                    foreach (ParameterInfo parameterInfo in propertyInfo.GetIndexParameters())
                        typeCollection.Add(parameterInfo.ParameterType);
 
                    this.parameters = typeCollection.ToArray();
 
                    // return type for property
                    this.returnType = propertyInfo.PropertyType;
                }
 
                this.hashCode = this.GetHashCodeImpl();
            }
 
            internal MemberSignature(string name, Type[] parameters, Type returnType)
            {
                this.name = name;
                this.returnType = returnType;
                if (parameters != null)
                    this.parameters = (Type[])parameters.Clone();
 
                this.hashCode = this.GetHashCodeImpl();
            }
 
            #endregion
 
            #region properties
 
            public string Name
            {
                get
                {
                    return name;
                }
            }
 
            public Type ReturnType
            {
                get
                {
                    return returnType;
                }
            }
 
            public Type[] Parameters
            {
                get
                {
                    if (parameters == null)
                        return null;
 
                    return (Type[])parameters.Clone();
                }
            }
 
 
            #endregion
 
            #region Comparison
 
            public override bool Equals(object obj)
            {
                MemberSignature memberSignature = obj as MemberSignature;
 
                if ((memberSignature == null) || (this.name != memberSignature.name) || (this.returnType != memberSignature.returnType))
                    return false;
 
                if ((this.Parameters == null) && (memberSignature.Parameters != null) ||
                    (this.Parameters != null) && (memberSignature.Parameters == null))
                    return false;
 
                if (this.Parameters != null)
                {
                    if (this.parameters.Length != memberSignature.parameters.Length)
                        return false;
 
                    for (int loop = 0; loop < this.parameters.Length; loop++)
                    {
                        if (this.parameters[loop] != memberSignature.parameters[loop])
                            return false;
                    }
                }
 
                return true;
            }
 
            // this method will filter using a mask signautre. only non-null mask members are used to filter 
            // the signature, the rest are ignored
            public bool FilterSignature(MemberSignature maskSignature)
            {
                if (maskSignature == null)
                    throw new ArgumentNullException("maskSignature");
 
                if (((maskSignature.Name != null) && (this.name != maskSignature.name)) ||
                    ((maskSignature.returnType != null) && (this.returnType != maskSignature.returnType)))
                    return false;
 
                if (maskSignature.parameters != null)
                {
                    if (this.parameters == null)
                        return false;
 
                    if (this.parameters.Length != maskSignature.parameters.Length)
                        return false;
 
                    for (int loop = 0; loop < this.parameters.Length; loop++)
                    {
                        if (!this.parameters[loop].Equals(maskSignature.parameters[loop]))
                            return false;
                    }
                }
 
                return true;
            }
 
            public override string ToString()
            {
                string str = string.Empty;
 
                if (returnType != null)
                    str = returnType.FullName + " ";
 
                if (name != null && name.Length != 0)
                    str += name;
 
                if (parameters != null && parameters.Length > 0)
                {
                    str += "(";
 
                    for (int i = 0; i < parameters.Length; i++)
                    {
                        if (i > 0)
                            str += ", ";
 
                        if (parameters[i] != null)
                        {
                            if (parameters[i].GetType() != null && parameters[i].GetType().IsByRef)
                                str += "ref ";
 
                            str += parameters[i].FullName;
                        }
                    }
 
                    str += ")";
                }
 
                return str;
            }
 
            public override int GetHashCode()
            {
                return this.hashCode;
            }
 
            int GetHashCodeImpl()
            {
                int hashCode = 0;
 
                if (this.name != null)
                {
                    hashCode = name.GetHashCode();
                }
 
                if (this.parameters != null && this.parameters.Length > 0)
                {
                    for (int i = 0; i < this.parameters.Length; i++)
                    {
                        if (this.parameters[i] != null)
                        {
                            hashCode ^= this.parameters[i].GetHashCode();
                        }
                    }
                }
 
                if (this.returnType != null)
                {
                    hashCode ^= this.returnType.GetHashCode();
                }
 
                return hashCode;
            }
 
            #endregion
        }
        #endregion
 
        #region ICloneable Members
 
        public object Clone()
        {
            return this;
        }
        #endregion
    }
}