File: System\Workflow\Activities\DynamicContractTypeBuilder.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.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics.CodeAnalysis;
    using System.Drawing.Design;
    using System.Net.Security;
    using System.Reflection;
    using System.Reflection.Emit;
    using System.ServiceModel;
    using System.Threading;
    using System.Workflow.Activities.Design;
    using System.Workflow.ComponentModel;
    using System.Workflow.ComponentModel.Compiler;
 
    internal static class DynamicContractTypeBuilder
    {
        internal static readonly DependencyProperty DynamicContractTypesProperty =
            DependencyProperty.RegisterAttached("DynamicContractTypes",
            typeof(Dictionary<string, ContractType>), typeof(DynamicContractTypeBuilder),
            new PropertyMetadata(null, DependencyPropertyOptions.NonSerialized));
 
        public static Type GetContractType(OperationInfo operationInfo, ReceiveActivity contextActivity)
        {
            if (operationInfo == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("operationInfo");
            }
 
            if (contextActivity == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contextActivity");
            }
 
            if (string.IsNullOrEmpty(operationInfo.ContractName))
            {
                return null;
            }
 
            Activity rootActivity = contextActivity.RootActivity;
            Dictionary<string, ContractType> contractTypes =
                rootActivity.GetValue(DynamicContractTypeBuilder.DynamicContractTypesProperty) as Dictionary<string, ContractType>;
 
            if (contractTypes == null)
            {
                Activity definition = rootActivity.GetValue(Activity.WorkflowDefinitionProperty) as Activity;
                if (definition != null)
                {
                    contractTypes = definition.GetValue(DynamicContractTypeBuilder.DynamicContractTypesProperty) as Dictionary<string, ContractType>;
                }
 
                if (contractTypes != null)
                {
                    rootActivity.SetValue(DynamicContractTypeBuilder.DynamicContractTypesProperty, contractTypes);
                }
            }
 
            if (contractTypes == null)
            {
                contractTypes = BuildContractTypes(rootActivity);
                rootActivity.SetValue(DynamicContractTypeBuilder.DynamicContractTypesProperty, contractTypes);
            }
 
            if (contractTypes.ContainsKey(operationInfo.ContractName))
            {
                return contractTypes[operationInfo.ContractName];
            }
 
            return null;
        }
 
        static Dictionary<string, ContractType> BuildContractTypes(Activity contextActivity)
        {
            if (contextActivity == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contextActivity");
            }
 
            Dictionary<string, ContractType> types = new Dictionary<string, ContractType>();
 
            Walker walker = new Walker(true);
            walker.FoundActivity += delegate(Walker w, WalkerEventArgs args)
            {
                ReceiveActivity currentActivity = args.CurrentActivity as ReceiveActivity;
                if (currentActivity == null)
                {
                    return;
                }
                OperationInfo operationInfo = currentActivity.ServiceOperationInfo as OperationInfo;
                if (operationInfo == null)
                {
                    return;
                }
 
                if (string.IsNullOrEmpty(operationInfo.ContractName) ||
                    string.IsNullOrEmpty(operationInfo.Name))
                {
                    return;
                }
 
                if (!types.ContainsKey(operationInfo.ContractName))
                {
                    types.Add(operationInfo.ContractName,
                        new ContractType(operationInfo.ContractName));
                }
 
                bool hasReturnValue = false;
                bool duplicatedPositions = false;
                int maxPosition = -1;
                List<int> parameterIndexs = new List<int>();
 
                foreach (OperationParameterInfo operationParameterInfo in operationInfo.Parameters)
                {
                    if (operationParameterInfo.Position == -1)
                    {
                        hasReturnValue = true;
                    }
                    else
                    {
                        maxPosition = (maxPosition < operationParameterInfo.Position) ? operationParameterInfo.Position : maxPosition;
                    }
 
                    if (parameterIndexs.Contains(operationParameterInfo.Position))
                    {
                        duplicatedPositions = true;
                        break;
                    }
                    else
                    {
                        parameterIndexs.Add(operationParameterInfo.Position);
                    }
                }
 
                if (duplicatedPositions ||
                    maxPosition > (operationInfo.Parameters.Count - (hasReturnValue ? 2 : 1)))
                {
                    return;
                }
 
                ContractType contract = types[operationInfo.ContractName];
                ContractMethodInfo methodInfo = new ContractMethodInfo(contract, operationInfo);
            };
 
            walker.Walk(contextActivity);
 
            return types;
        }
    }
}