File: System\Workflow\Activities\ContractType.cs
Project: ndp\cdf\src\NetFx35\System.WorkflowServices\System.WorkflowServices.csproj (System.WorkflowServices)
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------
 
#pragma warning disable 1634, 1691
namespace System.Workflow.Activities
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Globalization;
    using System.Reflection;
    using System.ServiceModel;
 
    internal sealed class ContractType : Type, ICloneable
    {
        private static readonly char[] elementDecorators = new char[] { '[', '*', '&' };
        private static readonly char[] nameSeparators = new char[] { '.', '+' };
 
        private Attribute[] attributes = null;
        private ConstructorInfo[] constructors = null;
        private EventInfo[] events = null;
        private FieldInfo[] fields = null;
        private string fullName;
        private Guid guid = Guid.Empty;
        private MethodInfo[] methods = null;
 
        private string name;
        private Type[] nestedTypes = Type.EmptyTypes;
        private PropertyInfo[] properties = null;
        private TypeAttributes typeAttributes;
 
        internal ContractType(string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(
                    "name", SR2.GetString(SR2.Error_ArgumentValueNullOrEmptyString));
            }
 
            this.fullName = name;
 
            this.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 = this.name.Substring(0, idx).LastIndexOfAny(nameSeparators);
            }
            else
            {
                idx = this.name.LastIndexOfAny(nameSeparators);
            }
 
            if (idx != -1)
            {
                this.name = this.fullName.Substring(idx + 1);
            }
 
            this.typeAttributes = TypeAttributes.Interface |
                TypeAttributes.Sealed |
                TypeAttributes.Public |
                TypeAttributes.Abstract;
 
            this.attributes = new Attribute[] { new ServiceContractAttribute() };
            this.methods = new MethodInfo[0];
        }
 
        public override Assembly Assembly
        {
            get
            {
                return null;
            }
        }
 
        public override string AssemblyQualifiedName
        {
            get
            {
                return this.FullName;
            }
        }
 
        public override Type BaseType
        {
            get
            {
                return null;
            }
        }
 
        public override Type DeclaringType
        {
            get
            {
                return null;
            }
        }
 
        public override string FullName
        {
            get
            {
                return this.fullName;
            }
        }
 
        public override Guid GUID
        {
            get
            {
                if (this.guid == Guid.Empty)
                {
                    this.guid = Guid.NewGuid();
                }
 
                return this.guid;
            }
        }
 
        public override Module Module
        {
            get
            {
                return null;
            }
        }
 
        public override string Name
        {
            get
            {
                return this.name;
            }
        }
 
        public override string Namespace
        {
            get
            {
                if (this.fullName == Name)
                {
                    return string.Empty;
                }
 
                return this.fullName.Substring(0, this.fullName.Length - Name.Length - 1);
            }
        }
 
        public override RuntimeTypeHandle TypeHandle
        {
            get
            {
#pragma warning suppress 56503
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new NotImplementedException(SR2.GetString(SR2.Error_RuntimeNotSupported)));
            }
        }
 
        public override Type UnderlyingSystemType
        {
            get
            {
                return this;
            }
        }
 
        public object Clone()
        {
            return this;
        }
 
        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return false;
            }
 
            ContractType contract = obj as ContractType;
            if (contract == null)
            {
                return false;
            }
 
            if (string.Compare(this.AssemblyQualifiedName, contract.AssemblyQualifiedName, StringComparison.Ordinal) != 0 ||
                this.methods.Length != contract.methods.Length)
            {
                return false;
            }
 
            foreach (MethodInfo methodInfo in this.methods)
            {
                if (this.GetMemberHelper<MethodInfo>(BindingFlags.Public | BindingFlags.Instance,
                    new MemberSignature(methodInfo),
                    ref contract.methods) == null)
                {
                    return false;
                }
            }
 
            return true;
        }
 
        public override int GetArrayRank()
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(
                SR2.GetString(SR2.Error_CurrentTypeNotAnArray));
        }
 
        public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
        {
            return GetMembersHelper<ConstructorInfo>(bindingAttr, ref this.constructors, false);
        }
 
        public override object[] GetCustomAttributes(bool inherit)
        {
            return GetCustomAttributes(typeof(object), inherit);
        }
 
        public override object[] GetCustomAttributes(Type attributeType, bool inherit)
        {
            if (attributeType == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("attributeType");
            }
 
            return ServiceOperationHelpers.GetCustomAttributes(attributeType, this.attributes);
        }
 
        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 GetElementType()
        {
            return null;
        }
 
        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 int GetHashCode()
        {
            return this.name.GetHashCode();
        }
 
        public override Type GetInterface(string name, bool ignoreCase)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(
                    "name", SR2.GetString(SR2.Error_ArgumentValueNullOrEmptyString));
            }
 
            if (string.Compare(this.name, name, StringComparison.Ordinal) == 0)
            {
                return this;
            }
            return null;
        }
 
        public override Type[] GetInterfaces()
        {
            return Type.EmptyTypes;
        }
 
        public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags 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)
        {
            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 MethodInfo[] GetMethods(BindingFlags bindingAttr)
        {
            return GetMembersHelper<MethodInfo>(bindingAttr, ref this.methods, true);
        }
 
        public override Type GetNestedType(string name, BindingFlags bindingAttr)
        {
            return null;
        }
 
        public override Type[] GetNestedTypes(BindingFlags bindingAttr)
        {
            return Type.EmptyTypes;
        }
 
        public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
        {
            return GetMembersHelper<PropertyInfo>(bindingAttr, ref this.properties, true);
        }
 
        public override object InvokeMember(string name, BindingFlags bindingFlags, Binder binder, object target, object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParams)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                new NotImplementedException(SR2.GetString(SR2.Error_RuntimeNotSupported)));
        }
 
        public override bool IsAssignableFrom(Type type)
        {
            if (type == null)
            {
                return false;
            }
            if (!(type is ContractType))
            {
                return false;
            }
            return (this.Equals((Object)type));
        }
 
        public override bool IsDefined(Type attributeType, bool inherit)
        {
            if (attributeType == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("attributeType");
            }
            return ServiceOperationHelpers.IsDefined(attributeType, attributes);
        }
 
        public override bool IsSubclassOf(Type type)
        {
            return false;
        }
 
        public override Type MakeByRefType()
        {
            return this;
        }
 
        public override string ToString()
        {
            return this.FullName;
        }
 
        internal void AddMethod(ContractMethodInfo methodInfo)
        {
            if (methodInfo == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("methodInfo");
            }
 
            MemberSignature signature = new MemberSignature(methodInfo);
            if (this.GetMemberHelper<MethodInfo>(BindingFlags.Public | BindingFlags.Instance,
                signature,
                ref this.methods) != null)
            {
                return;
            }
            else
            {
                List<MethodInfo> localMethods = new List<MethodInfo>();
                if (this.methods != null)
                {
                    localMethods.AddRange(this.methods);
                }
                localMethods.Add(methodInfo);
                this.methods = new MethodInfo[localMethods.Count];
                localMethods.CopyTo(this.methods);
            }
        }
 
        protected override TypeAttributes GetAttributeFlagsImpl()
        {
            return typeAttributes;
        }
 
        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 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 false;
        }
 
 
        protected override bool IsCOMObjectImpl()
        {
            return false;
        }
 
        protected override bool IsContextfulImpl()
        {
            return false;
        }
 
        protected override bool IsMarshalByRefImpl()
        {
            return false;
        }
 
        protected override bool IsPointerImpl()
        {
            return (this.name[this.name.Length - 1] == '*');
        }
 
        protected override bool IsPrimitiveImpl()
        {
            return false;
        }
 
        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 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))));
        }
 
        //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;
        //}
 
        // generic method that implements all GetXXX methods
        private T GetMemberHelper<T>(BindingFlags bindingAttr, MemberSignature memberSignature, ref T[] members)
            where T : MemberInfo
        {
            if (members != null)
            {
                // search the local type
                foreach (T memberInfo in members)
                {
                    MemberSignature candididateMemberSignature = new MemberSignature(memberInfo);
                    if (candididateMemberSignature.FilterSignature(memberSignature) && FilterMember(memberInfo, bindingAttr))
                    {
                        return memberInfo;
                    }
                }
            }
 
            return null;
        }
 
        // generic method that implements all GetXXXs methods
        private T[] GetMembersHelper<T>(BindingFlags bindingAttr, ref T[] members, bool searchBase)
            where T : MemberInfo
        {
            Dictionary<MemberSignature, T> membersDictionary = new Dictionary<MemberSignature, T>();
 
            if (members != null)
            {
                // 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 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();
        }
 
        internal class MemberSignature
        {
            private string name = null;
            private Type[] parameters = null;
            private Type returnType = null;
 
            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;
                }
 
            }
 
            internal MemberSignature(string name, Type[] parameters, Type returnType)
            {
                this.name = name;
                this.returnType = returnType;
                if (parameters != null)
                {
                    this.parameters = (Type[])parameters.Clone();
                }
            }
 
            public string Name
            {
                get
                {
                    return name;
                }
            }
 
            public Type[] Parameters
            {
                get
                {
                    if (parameters == null)
                    {
                        return null;
                    }
 
                    return (Type[])parameters.Clone();
                }
            }
 
            public Type ReturnType
            {
                get
                {
                    return returnType;
                }
            }
 
            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 DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("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 int GetHashCode()
            {
                return ToString().GetHashCode();
            }
 
            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;
            }
        }
    }
}