File: System\Workflow\Activities\TypedOperationInfo.cs
Project: ndp\cdf\src\NetFx35\System.WorkflowServices\System.WorkflowServices.csproj (System.WorkflowServices)
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------
 
namespace System.Workflow.Activities
{
    using System;
    using System.ComponentModel;
    using System.Drawing.Design;
    using System.Diagnostics.CodeAnalysis;
    using System.Net.Security;
    using System.Reflection;
    using System.ServiceModel;
    using System.ServiceModel.Description;
    using System.Workflow.ComponentModel;
    using System.Workflow.ComponentModel.Compiler;
    using System.Workflow.Activities.Design;
 
    [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
    public sealed class TypedOperationInfo : OperationInfoBase
    {
        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
        internal static readonly DependencyProperty ContractTypeProperty =
            DependencyProperty.Register("ContractType",
            typeof(Type), typeof(TypedOperationInfo),
            new PropertyMetadata(null, DependencyPropertyOptions.Metadata));
 
        public TypedOperationInfo()
        {
        }
 
        public TypedOperationInfo(Type contractType, string operationName)
        {
            if (contractType == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contractType");
            }
            if (string.IsNullOrEmpty(operationName))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("operationName",
                    SR2.GetString(SR2.Error_ArgumentValueNullOrEmptyString));
            }
 
            this.ContractType = contractType;
            this.Name = operationName;
        }
 
        public Type ContractType
        {
            get { return (Type) this.GetValue(TypedOperationInfo.ContractTypeProperty); }
            set { this.SetValue(TypedOperationInfo.ContractTypeProperty, value); }
        }
 
        public override OperationInfoBase Clone()
        {
            TypedOperationInfo clonedOperation = (TypedOperationInfo) base.Clone();
            clonedOperation.ContractType = this.ContractType;
 
            return clonedOperation;
        }
 
        public override bool Equals(object obj)
        {
            if (!base.Equals(obj))
            {
                return false;
            }
 
            TypedOperationInfo operationInfo = obj as TypedOperationInfo;
            if (operationInfo == null)
            {
                return false;
            }
            if (this.ContractType != operationInfo.ContractType)
            {
                return false;
            }
 
            return true;
        }
 
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
 
        public override string ToString()
        {
            string returnValue = string.Empty;
            if (!string.IsNullOrEmpty(this.Name))
            {
                returnValue = this.Name;
 
                if (this.ContractType != null)
                {
                    returnValue = this.ContractType.FullName + "." + returnValue;
                }
            }
 
            return returnValue;
        }
 
        protected internal override string GetContractFullName(IServiceProvider provider)
        {
            if (this.ContractType != null)
            {
                return this.ContractType.FullName;
            }
            return string.Empty;
        }
 
        internal protected override Type GetContractType(IServiceProvider provider)
        {
            if (this.ContractType == null)
            {
                return null;
            }
 
            ITypeProvider typeProvider = null;
 
            if (provider != null)
            {
                typeProvider = provider.GetService(typeof(ITypeProvider)) as ITypeProvider;
            }
 
            Type contractType = this.ContractType;
            if (!this.IsReadOnly && contractType != null && typeProvider != null)
            {
                //Get the type from TypeProvider in case the type definition has changed in the local assembly.
                // the refresh is needed if contractType is a designtime type or is in the runtime type from the built assembly
                if (contractType is DesignTimeType ||
                    (typeProvider.LocalAssembly != null && typeProvider.LocalAssembly.Equals(contractType.Assembly)))
                {
                    Type currentDesignTimeType = typeProvider.GetType(contractType.AssemblyQualifiedName);
                    if (currentDesignTimeType != null)
                    {
                        this.ContractType = currentDesignTimeType;
                        this.RemoveProperty(OperationInfoBase.MethodInfoProperty);
                    }
                }
            }
 
            return this.ContractType;
        }
 
        internal protected override bool GetIsOneWay(IServiceProvider provider)
        {
            MethodInfo methodInfo = this.GetMethodInfo(provider);
            if (methodInfo != null)
            {
                object[] operationContractAttribs =
                    methodInfo.GetCustomAttributes(typeof(OperationContractAttribute), true);
 
                if (operationContractAttribs != null && operationContractAttribs.Length > 0)
                {
                    if (operationContractAttribs[0] is OperationContractAttribute)
                    {
                        return ((OperationContractAttribute) operationContractAttribs[0]).IsOneWay;
                    }
                    if (operationContractAttribs[0] is AttributeInfoAttribute)
                    {
                        AttributeInfoAttribute attribInfoAttrib = operationContractAttribs[0] as AttributeInfoAttribute;
                        return GetAttributePropertyValue<bool>(provider,
                            attribInfoAttrib.AttributeInfo,
                            "IsOneWay");
                    }
                }
            }
 
            return false;
        }
 
        internal protected override MethodInfo GetMethodInfo(IServiceProvider provider)
        {
            if (string.IsNullOrEmpty(this.Name))
            {
                return null;
            }
 
            MethodInfo methodInfo = null;
            if (this.IsReadOnly)
            {
                if (this.UserData.Contains(OperationInfoBase.MethodInfoProperty))
                {
                    methodInfo = this.UserData[OperationInfoBase.MethodInfoProperty] as MethodInfo;
                }
 
                if (methodInfo != null)
                {
                    return methodInfo;
                }
            }
 
            Type type = this.GetContractType(provider);
            if (type != null && ServiceOperationHelpers.IsValidServiceContract(type))
            {
                methodInfo = this.InternalGetMethodInfo(provider, type);
            }
 
            if (this.IsReadOnly)
            {
                this.UserData[OperationInfoBase.MethodInfoProperty] = methodInfo;
            }
 
            return methodInfo;
        }
 
        internal protected override OperationParameterInfoCollection GetParameters(IServiceProvider provider)
        {
            OperationParameterInfoCollection parameters = new OperationParameterInfoCollection();
 
            MethodInfo methodInfo = this.GetMethodInfo(provider);
            if (methodInfo != null)
            {
                foreach (ParameterInfo parameter in methodInfo.GetParameters())
                {
                    if (parameters[parameter.Name] == null)
                    {
                        parameters.Add(new OperationParameterInfo(parameter));
                    }
                }
 
                if (methodInfo.ReturnParameter != null && methodInfo.ReturnParameter.ParameterType != typeof(void))
                {
                    if (parameters["(ReturnValue)"] == null)
                    {
                        OperationParameterInfo parameterInfo = new OperationParameterInfo(methodInfo.ReturnParameter);
                        parameterInfo.Name = "(ReturnValue)";
                        parameters.Add(parameterInfo);
                    }
                }
            }
 
            return parameters;
        }
 
        private static string[] GetAttributePropertyNames(AttributeInfo attributeInfo)
        {
            if (attributeInfo == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("attributeInfo");
            }
 
            string[] argumentNames = null;
            BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic;
            FieldInfo argumentNamesField = typeof(AttributeInfo).GetField("argumentNames", bindingFlags);
            if (argumentNamesField != null)
            {
                argumentNames = argumentNamesField.GetValue(attributeInfo) as string[];
            }
 
            return argumentNames;
        }
 
        T GetAttributePropertyValue<T>(IServiceProvider provider, AttributeInfo attribInfo, string propertyName)
        {
            string[] argumentNames = GetAttributePropertyNames(attribInfo);
            int argumentIndex = -1;
            for (int index = 0; index < argumentNames.Length; index++)
            {
                // skip unnamed arguments these are constructor arguments
                if ((argumentNames[index] == null) || (argumentNames[index].Length == 0))
                {
                    continue;
                }
                else
                {
                    if (argumentNames[index].Equals(propertyName))
                    {
                        argumentIndex = index;
                        break;
                    }
                }
            }
            if (argumentIndex != -1)
            {
                return (T) attribInfo.GetArgumentValueAs(provider, argumentIndex, typeof(T));
            }
            else
            {
                return default(T);
            }
        }
 
        MethodInfo InternalGetMethodInfo(IServiceProvider provider, Type contractType)
        {
            MethodInfo methodInfo = null;
 
            if (contractType != null && ServiceOperationHelpers.IsValidServiceContract(contractType))
            {
                foreach (MethodInfo currentMethodInfo in contractType.GetMethods())
                {
                    object[] operationContractAttribs =
                        currentMethodInfo.GetCustomAttributes(typeof(OperationContractAttribute), true);
 
                    if (operationContractAttribs != null && operationContractAttribs.Length > 0)
                    {
                        string operationName = null;
                        if (operationContractAttribs[0] is OperationContractAttribute)
                        {
                            OperationContractAttribute operationContractAttribute =
                                operationContractAttribs[0] as OperationContractAttribute;
 
                            operationName = operationContractAttribute.Name;
                        }
                        if (operationContractAttribs[0] is AttributeInfoAttribute)
                        {
                            AttributeInfoAttribute attribInfoAttrib =
                                operationContractAttribs[0] as AttributeInfoAttribute;
 
                            operationName = GetAttributePropertyValue<string>(provider,
                                attribInfoAttrib.AttributeInfo,
                                "Name");
                        }
 
                        if (string.IsNullOrEmpty(operationName) &&
                            string.Compare(currentMethodInfo.Name, this.Name, StringComparison.Ordinal) == 0)
                        {
                            methodInfo = currentMethodInfo;
                            break;
                        }
                        else if (string.Compare(operationName, this.Name, StringComparison.Ordinal) == 0)
                        {
                            methodInfo = currentMethodInfo;
                            break;
                        }
                    }
                }
            }
 
            if (methodInfo == null)
            {
                foreach (Type parentContract in contractType.GetInterfaces())
                {
                    methodInfo = this.InternalGetMethodInfo(provider, parentContract);
                    if (methodInfo != null)
                    {
                        break;
                    }
                }
            }
 
            return methodInfo;
        }
    }
}