CorrelationValidator.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WF / Activities / CorrelationValidator.cs / 1305376 / CorrelationValidator.cs

                            #region Imports 

using System;
using System.Reflection;
using System.Collections; 
using System.ComponentModel;
using System.Collections.Generic; 
using System.Runtime.Serialization; 
using System.ComponentModel.Design;
using System.Collections.Specialized; 
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel.Compiler;
using System.ComponentModel.Design.Serialization; 
using System.CodeDom;
using System.Globalization; 
using System.Workflow.Runtime; 
using System.Workflow.Activities.Common;
 
#endregion

namespace System.Workflow.Activities
{ 
    internal static class CorrelationSetsValidator
    { 
        internal static ValidationErrorCollection Validate(ValidationManager manager, Object obj) 
        {
            ValidationErrorCollection validationErrors = new ValidationErrorCollection(); 

            Activity activity = obj as Activity;
            if (!(activity is CallExternalMethodActivity) && !(activity is HandleExternalEventActivity))
                throw new ArgumentException(SR.GetString(SR.Error_UnexpectedArgumentType, typeof(Activity).FullName), "obj"); 

            Type interfaceType = (activity is CallExternalMethodActivity) ? ((CallExternalMethodActivity)activity).InterfaceType : ((HandleExternalEventActivity)activity).InterfaceType; 
            if (interfaceType == null) 
                return validationErrors;
 
            if (interfaceType.ContainsGenericParameters)
            {
               ValidationError error = new ValidationError(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_GenericMethodsNotSupported), interfaceType.FullName), ErrorNumbers.Error_GenericMethodsNotSupported);
                error.PropertyName = "InterfaceType"; 
                validationErrors.Add(error);
                return validationErrors; 
            } 

            object[] attributes = interfaceType.GetCustomAttributes(typeof(ExternalDataExchangeAttribute), false); 
            if (attributes.Length == 0)
            {
                ValidationError error = new ValidationError(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_ExternalDataExchangeException), interfaceType.FullName), ErrorNumbers.Error_TypeNotExist);
                error.PropertyName = "InterfaceType"; 
                validationErrors.Add(error);
                return validationErrors; 
            } 

            if (activity.Site == null) 
            {
                ValidationErrorCollection interfaceErrors = ValidateHostInterface(manager, interfaceType, activity);
                if (interfaceErrors.Count != 0)
                { 
                    validationErrors.AddRange(interfaceErrors);
                    return validationErrors; 
                } 
            }
 
            MemberInfo targetMember = null;
            if (activity is CallExternalMethodActivity)
            {
                if (((CallExternalMethodActivity)activity).MethodName == null || ((CallExternalMethodActivity)activity).MethodName.Length == 0) 
                    return validationErrors;
 
                MethodInfo methodInfo = interfaceType.GetMethod(((CallExternalMethodActivity)activity).MethodName, BindingFlags.Instance | BindingFlags.Public); 
                if (methodInfo == null || methodInfo.IsSpecialName)
                { 
                    validationErrors.Add(new ValidationError(SR.GetString(SR.Error_MissingMethodName, activity.Name, ((CallExternalMethodActivity)activity).MethodName), ErrorNumbers.Error_MissingMethodName));
                    return validationErrors;
                }
                if (methodInfo.ContainsGenericParameters) 
                {
                    ValidationError error = new ValidationError(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_GenericMethodsNotSupported), methodInfo.Name), ErrorNumbers.Error_GenericMethodsNotSupported); 
                    error.PropertyName = "MethodName"; 
                    validationErrors.Add(error);
                    return validationErrors; 
                }
                targetMember = methodInfo;
            }
            else 
            {
                if (((HandleExternalEventActivity)activity).EventName == null || ((HandleExternalEventActivity)activity).EventName.Length == 0) 
                    return validationErrors; 

                EventInfo eventInfo = interfaceType.GetEvent(((HandleExternalEventActivity)activity).EventName, BindingFlags.Instance | BindingFlags.Public); 
                if (eventInfo == null)
                {
                    validationErrors.Add(new ValidationError(SR.GetString(SR.Error_MissingEventName, activity.Name, ((HandleExternalEventActivity)activity).EventName), ErrorNumbers.Error_MissingMethodName));
                    return validationErrors; 
                }
                targetMember = eventInfo; 
            } 

            attributes = interfaceType.GetCustomAttributes(typeof(CorrelationProviderAttribute), false); 
            if (attributes.Length != 0)
                return validationErrors;

            CorrelationToken correlator = activity.GetValue((activity is CallExternalMethodActivity) ? CallExternalMethodActivity.CorrelationTokenProperty : HandleExternalEventActivity.CorrelationTokenProperty) as CorrelationToken; 

            object[] correlationParameterAttributes = interfaceType.GetCustomAttributes(typeof(CorrelationParameterAttribute), false); 
            if (correlationParameterAttributes.Length == 0) 
            {
                if (correlator != null) 
                    validationErrors.Add(new ValidationError(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_CorrelationTokenSpecifiedForUncorrelatedInterface), activity.QualifiedName, interfaceType), ErrorNumbers.Error_InvalidIdentifier, false, "CorrelationToken"));

                return validationErrors;
            } 

            // Someone derived from the activity and compiled, don't generate errors (P || C) validation. 
            if (activity.Parent == null) 
                return validationErrors;
 
            if (correlator == null || String.IsNullOrEmpty(correlator.Name))
            {
                validationErrors.Add(new ValidationError(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_MissingCorrelationTokenProperty), activity.QualifiedName), ErrorNumbers.Error_ParameterPropertyNotSet, false, "CorrelationToken"));
                return validationErrors; 
            }
 
            if (String.IsNullOrEmpty(correlator.OwnerActivityName)) 
            {
                validationErrors.Add(new ValidationError(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_MissingCorrelationTokenOwnerNameProperty), activity.QualifiedName), ErrorNumbers.Error_ParameterPropertyNotSet, false, "CorrelationToken")); 
                return validationErrors;
            }

            string qualifiedCorrelationToken = null; 
            Activity sourceActivity = activity.GetActivityByName(correlator.OwnerActivityName);
            if (sourceActivity == null) 
                sourceActivity = Helpers.ParseActivityForBind(activity, correlator.OwnerActivityName); 
            if (sourceActivity != null)
                qualifiedCorrelationToken = sourceActivity.QualifiedName; 

            Activity replicatorParent = null;
            CompositeActivity parent = activity.Parent;
            Activity rootActivity = parent; 
            bool ownerIsParent = false;
            while (parent != null) 
            { 
                // We hardcode Replicator here, not MultiInstance | Concurrent.
                if (parent is ReplicatorActivity && replicatorParent == null) 
                    replicatorParent = parent;

                if (qualifiedCorrelationToken == parent.QualifiedName)
                    ownerIsParent = true; 

                rootActivity = parent; 
                parent = parent.Parent; 

            } 

            if (!ownerIsParent)
            {
                ValidationError error = new ValidationError(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_OwnerActivityIsNotParent),activity.QualifiedName), ErrorNumbers.Error_ParameterPropertyNotSet); 
                error.PropertyName = "CorrelationToken";
                validationErrors.Add(error); 
            } 

            bool initializer = false; 
            attributes = targetMember.GetCustomAttributes(typeof(CorrelationInitializerAttribute), false) as object[];
            if (attributes.Length > 0)
                initializer = true;
 
            if (initializer)
            { 
                if (replicatorParent != null && activity is HandleExternalEventActivity) 
                {
                    ValidationError error = new ValidationError(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_InitializerInReplicator), replicatorParent.QualifiedName), ErrorNumbers.Error_InitializerInReplicator, false); 
                    error.PropertyName = "CorrelationToken";
                    validationErrors.Add(error);
                }
            } 

            if (!string.IsNullOrEmpty(qualifiedCorrelationToken)) 
            { 
                if (replicatorParent != null)
                { 
                    bool isValid = false;
                    Walker walker = new Walker();
                    walker.FoundActivity += delegate(Walker w, WalkerEventArgs args)
                    { 
                        if (!args.CurrentActivity.Enabled)
                            return; 
 
                        if (args.CurrentActivity.QualifiedName == qualifiedCorrelationToken)
                        { 
                            isValid = true;
                            args.Action = WalkerAction.Abort;
                            return;
                        } 
                    };
 
                    walker.Walk(replicatorParent); 
                    if (!isValid)
                    { 
                        ValidationError error = new ValidationError(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_CorrelationTokenInReplicator, correlator.Name, replicatorParent.QualifiedName)), ErrorNumbers.Error_CorrelationTokenInReplicator, true);
                        error.PropertyName = "CorrelationToken";
                        validationErrors.Add(error);
                    } 
                }
 
                //if (rootActivity is RootActivity) 
                {
                    if(!initializer) 
                    {
                        bool isValid = false;
                        bool ownerNameValidated = false;
                        bool initFollowerInTxnlScope = false; 
                        Walker walker = new Walker();
                        walker.FoundActivity += delegate(Walker w, WalkerEventArgs args) 
                        { 
                            Activity currentActivity = args.CurrentActivity;
                            if (!currentActivity.Enabled) 
                                return;

                            if (!(currentActivity is CallExternalMethodActivity) && !(currentActivity is HandleExternalEventActivity))
                                return; 

                            CorrelationToken existingCorrelationTokenValue = currentActivity.GetValue((currentActivity is CallExternalMethodActivity) ? CallExternalMethodActivity.CorrelationTokenProperty : HandleExternalEventActivity.CorrelationTokenProperty) as CorrelationToken; 
                            if (existingCorrelationTokenValue == null) 
                                return;
 
                            if (currentActivity is CallExternalMethodActivity && !interfaceType.Equals(((CallExternalMethodActivity)currentActivity).InterfaceType))
                                return;
                            else if (currentActivity is HandleExternalEventActivity && !interfaceType.Equals(((HandleExternalEventActivity)currentActivity).InterfaceType))
                                return; 

                            MemberInfo existingTargetMember = null; 
                            if (currentActivity is CallExternalMethodActivity) 
                            {
                                if (((CallExternalMethodActivity)currentActivity).MethodName == null || ((CallExternalMethodActivity)currentActivity).MethodName.Length == 0) 
                                    return;

                                MethodInfo methodInfo = interfaceType.GetMethod(((CallExternalMethodActivity)currentActivity).MethodName, BindingFlags.Instance | BindingFlags.Public);
                                if (methodInfo == null || methodInfo.IsSpecialName) 
                                    return;
 
                                existingTargetMember = methodInfo; 
                            }
                            else 
                            {
                                if (((HandleExternalEventActivity)currentActivity).EventName == null || ((HandleExternalEventActivity)currentActivity).EventName.Length == 0)
                                    return;
 
                                EventInfo eventInfo = interfaceType.GetEvent(((HandleExternalEventActivity)currentActivity).EventName, BindingFlags.Instance | BindingFlags.Public);
                                if (eventInfo == null) 
                                    return; 

                                existingTargetMember = eventInfo; 
                            }

                            attributes = existingTargetMember.GetCustomAttributes(typeof(CorrelationInitializerAttribute), false) as object[];
                            if (attributes.Length == 0) 
                                return;
 
                            if (activity is HandleExternalEventActivity) 
                            {
                                Activity txnlParent = GetTransactionalScopeParent(currentActivity); 
                                if (txnlParent != null && IsFollowerInTxnlScope(txnlParent, activity))
                                    initFollowerInTxnlScope = true;
                            }
 
                            string existingQualifiedCorrelationToken = null;
                            sourceActivity = activity.GetActivityByName(existingCorrelationTokenValue.OwnerActivityName); 
                            if (sourceActivity == null) 
                                sourceActivity = Helpers.ParseActivityForBind(activity, existingCorrelationTokenValue.OwnerActivityName);
                            if (sourceActivity != null) 
                                existingQualifiedCorrelationToken = sourceActivity.QualifiedName;

                            if ((correlator.Name == existingCorrelationTokenValue.Name) &&
                                IsOwnerActivitySame(correlator.OwnerActivityName, existingCorrelationTokenValue.OwnerActivityName, activity, currentActivity)) 
                            {
                                isValid = true; 
                                ownerNameValidated = true; 
                                args.Action = WalkerAction.Abort;
                                return; 
                            }
                        };

                        walker.Walk(rootActivity); 

                        if (!isValid) 
                        { 
                            ValidationError error = new ValidationError(string.Format(CultureInfo.CurrentCulture,SR.GetString(SR.Error_UninitializedCorrelation)), ErrorNumbers.Error_UninitializedCorrelation, true);
                            error.PropertyName = "CorrelationToken"; 
                            validationErrors.Add(error);
                            if (ownerNameValidated)
                            {
                                error = new ValidationError(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_MisMatchCorrelationTokenOwnerNameProperty), correlator.Name), ErrorNumbers.Error_UninitializedCorrelation, false); 
                                error.PropertyName = "CorrelationToken";
                                validationErrors.Add(error); 
                            } 
                        }
 
                        if (initFollowerInTxnlScope)
                        {
                            ValidationError error = new ValidationError(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_InitializerFollowerInTxnlScope)), ErrorNumbers.Error_InitializerFollowerInTxnlScope, false);
                            error.PropertyName = "CorrelationToken"; 
                            validationErrors.Add(error);
                        } 
                    } 
                }
            } 

            return validationErrors;
        }
 
        private static Activity GetTransactionalScopeParent(Activity activity)
        { 
            Activity parent = activity; 
            while (parent != null)
            { 
                if (parent is CompensatableTransactionScopeActivity || parent is TransactionScopeActivity)
                {
                    return parent;
                } 
                parent = parent.Parent;
            } 
            return parent; 
        }
 
        private static bool IsFollowerInTxnlScope(Activity parent, Activity activity)
        {
            Activity currentParent = activity;
            while (currentParent != null) 
            {
                if (currentParent == parent) 
                { 
                    return true;
                } 
                currentParent = currentParent.Parent;
            }
            return false;
        } 

        private static bool IsOwnerActivitySame(string ownerActivityName, string existingOwnerActivityName, Activity currentActivity, Activity existingActivity) 
        { 
            if(ownerActivityName.Equals(existingOwnerActivityName))
                return true; 

            Activity owner = currentActivity.GetActivityByName(ownerActivityName);
            if (owner == null)
                owner = Helpers.ParseActivityForBind(currentActivity, ownerActivityName); 

            Activity existingowner = currentActivity.GetActivityByName(existingOwnerActivityName); 
            if (existingowner == null) 
                existingowner = Helpers.ParseActivityForBind(existingActivity, existingOwnerActivityName);
 
            if (owner != null && existingowner != null && owner.QualifiedName.Equals(existingowner.QualifiedName))
                return true;

            return false; 
        }
 
        private static ValidationErrorCollection ValidateHostInterface(IServiceProvider serviceProvider, Type interfaceType, Activity activity) 
        {
            Dictionary typesValidated = serviceProvider.GetService(typeof(Dictionary)) as Dictionary; 

            if (typesValidated == null)
            {
                typesValidated = new Dictionary(); 
                IServiceContainer serviceContainer = serviceProvider.GetService(typeof(IServiceContainer)) as IServiceContainer;
                if (serviceContainer != null) 
                    serviceContainer.AddService(typeof(Dictionary), typesValidated); 
            }
 
            if (typesValidated.ContainsKey(interfaceType))
                return new ValidationErrorCollection();

            typesValidated.Add(interfaceType, new ValidationErrorCollection()); 

            object[] attributes = interfaceType.GetCustomAttributes(typeof(CorrelationProviderAttribute), false); 
            if (attributes.Length == 0) 
            {
                object[] dsAttribs = interfaceType.GetCustomAttributes(typeof(ExternalDataExchangeAttribute), false); 
                object[] corrParamAttribs = interfaceType.GetCustomAttributes(typeof(CorrelationParameterAttribute), false);

                if (dsAttribs.Length != 0 && corrParamAttribs.Length != 0)
                { 
                    typesValidated[interfaceType].AddRange(ValidateHostInterfaceMembers(interfaceType, activity));
                    typesValidated[interfaceType].AddRange(ValidateHostInterfaceAttributes(interfaceType)); 
                } 
                else
                { 
                    typesValidated[interfaceType].AddRange(ValidateInvalidHostInterfaceAttributes(interfaceType));
                }
            }
 
            return typesValidated[interfaceType];
        } 
 
        private static ValidationErrorCollection ValidateHostInterfaceMembers(Type interfaceType, Activity activity)
        { 
            ValidationErrorCollection validationErrors = new ValidationErrorCollection();

            foreach (MemberInfo memberInfo in interfaceType.GetMembers())
            { 
                if (!(memberInfo is MethodInfo) && !(memberInfo is EventInfo))
                    continue; 
 
                if ((memberInfo is MethodInfo) && ((MethodInfo)memberInfo).IsSpecialName)
                    continue; 

                MethodInfo methodInfo = null;
                Type delegateType = null;
                if (memberInfo is EventInfo) 
                {
                    EventInfo eventInfo = (EventInfo)memberInfo; 
                    delegateType = eventInfo.EventHandlerType; 
                    if (delegateType == null)
                        delegateType = TypeProvider.GetEventHandlerType(eventInfo); 

                    if (delegateType == null)
                        throw new InvalidOperationException();
 
                    methodInfo = delegateType.GetMethod("Invoke");
                } 
                else 
                    methodInfo = (MethodInfo)memberInfo;
 
                if (methodInfo.IsGenericMethod)
                {
                    ValidationError error = new ValidationError(
                        string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_GenericMethodsNotSupported), (memberInfo is EventInfo) ? delegateType.Name : methodInfo.Name), ErrorNumbers.Error_GenericMethodsNotSupported); 
                    if (memberInfo is EventInfo)
                        error.UserData.Add(typeof(EventInfo), ((EventInfo)memberInfo).Name); 
                    else 
                        error.UserData.Add(typeof(MethodInfo), methodInfo.Name);
                    validationErrors.Add(error); 
                }

                if (methodInfo.ReturnType != typeof(void) && (memberInfo is EventInfo))
                { 
                    ValidationError error = new ValidationError(
                        string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_ReturnTypeNotVoid), (memberInfo is EventInfo) ? delegateType.Name : methodInfo.Name), ErrorNumbers.Error_ReturnTypeNotVoid); 
                    if (memberInfo is EventInfo) 
                        error.UserData.Add(typeof(EventInfo), ((EventInfo)memberInfo).Name);
                    else 
                        error.UserData.Add(typeof(MethodInfo), methodInfo.Name);
                    validationErrors.Add(error);
                }
 
                foreach (ParameterInfo param in methodInfo.GetParameters())
                { 
                    if (param.IsOut || param.IsRetval) 
                    {
                        ValidationError error = new ValidationError( 
                            string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_OutRefParameterNotSupported), (memberInfo is EventInfo) ? delegateType.Name : methodInfo.Name, param.Name), ErrorNumbers.Error_OutRefParameterNotSupported);
                        if (memberInfo is EventInfo)
                            error.UserData.Add(typeof(EventInfo), ((EventInfo)memberInfo).Name);
                        else 
                            error.UserData.Add(typeof(MethodInfo), methodInfo.Name);
                        error.UserData.Add(typeof(ParameterInfo), param.Name); 
                        validationErrors.Add(error); 
                    }
                } 
            }

            return validationErrors;
        } 

        private static ValidationErrorCollection ValidateHostInterfaceAttributes(Type interfaceType) 
        { 
            if (interfaceType == null)
                throw new ArgumentNullException("interfaceType"); 

            ValidationErrorCollection validationErrors = new ValidationErrorCollection();
            ArrayList parameterAttrs = new ArrayList();
            foreach (object interfaceAttribute in interfaceType.GetCustomAttributes(typeof(CorrelationParameterAttribute), false)) 
            {
                CorrelationParameterAttribute parameterAttribute = Helpers.GetAttributeFromObject(interfaceAttribute); 
                if (String.IsNullOrEmpty(parameterAttribute.Name) || parameterAttribute.Name.Trim().Length == 0) 
                {
                    ValidationError error = new ValidationError(SR.GetString(CultureInfo.CurrentCulture,SR.Error_CorrelationAttributeInvalid, typeof(CorrelationParameterAttribute).Name, "Name", interfaceType.Name), ErrorNumbers.Error_CorrelationAttributeInvalid); 
                    error.UserData.Add(typeof(CorrelationParameterAttribute), interfaceType.Name);
                    validationErrors.Add(error);
                    continue;
                } 
                if (parameterAttrs.Contains(parameterAttribute.Name))
                { 
                    ValidationError error = new ValidationError(SR.GetString(CultureInfo.CurrentCulture,SR.Error_DuplicateCorrelationAttribute, typeof(CorrelationParameterAttribute).Name, parameterAttribute.Name, interfaceType.Name), ErrorNumbers.Error_DuplicateCorrelationAttribute); 
                    error.UserData.Add(typeof(CorrelationParameterAttribute), interfaceType.Name);
                    validationErrors.Add(error); 
                    continue;
                }
                parameterAttrs.Add(parameterAttribute.Name);
            } 

            Hashtable paramTypes = new Hashtable(); 
            Hashtable memberInfoCorrelationAliasAttrs = new Hashtable(); // MemberInfo -> CorrelationAliases 
            Hashtable delegateTypeCorrelationAliasAttrs = new Hashtable(); // Delegate type -> CorrelationAliases
            int initializerCount = 0; 
            foreach (MemberInfo memberInfo in interfaceType.GetMembers())
            {
                if (memberInfo is MethodInfo && !((MethodInfo)memberInfo).IsSpecialName)
                { 
                    Hashtable correlationAliasAttrs = new Hashtable();
                    memberInfoCorrelationAliasAttrs.Add(memberInfo, correlationAliasAttrs); 
                    FillCorrelationAliasAttrs(memberInfo, correlationAliasAttrs, validationErrors); 
                    int aliasLength = memberInfo.GetCustomAttributes(typeof(CorrelationInitializerAttribute), false).Length;
                    initializerCount += aliasLength; 
                    if (aliasLength > 0)
                    {
                        foreach (string paramName in parameterAttrs)
                        { 
                            string paramPath = paramName;
                            if (correlationAliasAttrs.Contains(paramName)) 
                                paramPath = ((CorrelationAliasAttribute)correlationAliasAttrs[paramName]).Path; 

                            Type paramType = FetchParameterType(memberInfo, paramPath); 
                            if (paramType != null)
                            {
                                if (!paramTypes.ContainsKey(paramName))
                                    paramTypes[paramName] = paramType; 
                            }
                        } 
                    } 
                }
                else if (memberInfo is EventInfo) 
                {
                    int aliasLength = memberInfo.GetCustomAttributes(typeof(CorrelationInitializerAttribute), false).Length;
                    initializerCount += aliasLength;
 
                    // Add event info it's delegate's CorrelationAliasAttributes
                    // to memberInfoCorrelationAliasAttrs against the EventInfo. 
                    Hashtable correlationAliasAttrs = new Hashtable(); 
                    memberInfoCorrelationAliasAttrs.Add(memberInfo, correlationAliasAttrs);
                    FillCorrelationAliasAttrs(memberInfo, correlationAliasAttrs, validationErrors); 
                    Type delegateType = Helpers.GetDelegateFromEvent((EventInfo)memberInfo);
                    MethodInfo delegateMethod = delegateType.GetMethod("Invoke");
                    FillCorrelationAliasAttrs(delegateType, correlationAliasAttrs, validationErrors);
 
                    // Add event delegate's CorrelationAliasAttributes
                    // to delegateTypeCorrelationAliasAttrs against the deletgate type. 
                    Hashtable delegateCorrelationAliasAttrs = new Hashtable(); 
                    FillCorrelationAliasAttrs(delegateType, delegateCorrelationAliasAttrs, validationErrors);
                    if (delegateTypeCorrelationAliasAttrs[delegateType] == null) 
                        delegateTypeCorrelationAliasAttrs.Add(delegateType, delegateCorrelationAliasAttrs);

                    if (aliasLength > 0)
                    { 
                        foreach (string paramName in parameterAttrs)
                        { 
                            string paramPath = paramName; 
                            if (correlationAliasAttrs.Contains(paramName))
                                paramPath = ((CorrelationAliasAttribute)correlationAliasAttrs[paramName]).Path; 

                            Type paramType = FetchParameterType(memberInfo, paramPath);
                            if (paramType != null)
                            { 
                                if (!paramTypes.ContainsKey(paramName))
                                    paramTypes[paramName] = paramType; 
                            } 
                        }
                    } 
                }
            }

            // validate : correlaion alias has corresponding parameter 
            foreach (DictionaryEntry memberEntry in memberInfoCorrelationAliasAttrs)
            { 
                MemberInfo memberInfo = memberEntry.Key as MemberInfo; 
                Hashtable correlationAliasAttrs = (Hashtable)memberEntry.Value;
                foreach (string paramName in correlationAliasAttrs.Keys) 
                {
                    if (!parameterAttrs.Contains(paramName))
                    {
                        // Ignore the error if the alias attribute is from the event delegate. 
                        if (memberInfo is EventInfo && ((Hashtable)delegateTypeCorrelationAliasAttrs[Helpers.GetDelegateFromEvent((EventInfo)memberInfo)])[paramName] != null)
                            continue; 
 
                        ValidationError error = new ValidationError(SR.GetString(CultureInfo.CurrentCulture,SR.Error_CorrelationParameterNotFound, typeof(CorrelationAliasAttribute).Name, paramName, memberInfo.Name, typeof(CorrelationParameterAttribute).Name, interfaceType.Name), ErrorNumbers.Error_CorrelationParameterNotFound);
                        error.UserData.Add(typeof(CorrelationAliasAttribute), memberInfo.Name); 
                        validationErrors.Add(error);
                    }
                }
            } 

            // validate : correlation parameters has valid entries in all members 
            foreach (string paramName in parameterAttrs) 
            {
                foreach (DictionaryEntry memberEntry in memberInfoCorrelationAliasAttrs) 
                {
                    string paramPath = paramName;
                    MemberInfo memberInfo = (MemberInfo)memberEntry.Key;
                    Hashtable correlationAliasAttrs = (Hashtable)memberEntry.Value; 
                    if (correlationAliasAttrs.Contains(paramName))
                        paramPath = ((CorrelationAliasAttribute)correlationAliasAttrs[paramName]).Path; 
 
                    Type paramType = FetchParameterType((MemberInfo)memberEntry.Key, paramPath);
                    if (paramType == null) 
                    {
                        // Ignore the error if the alias attribute is from the event delegate.
                        if (memberInfo is EventInfo && ((Hashtable)delegateTypeCorrelationAliasAttrs[Helpers.GetDelegateFromEvent((EventInfo)memberInfo)])[paramName] != null)
                            continue; 

                        //error path not resolved 
                        ValidationError error = new ValidationError(SR.GetString(CultureInfo.CurrentCulture,SR.Error_CorrelationInvalid,(memberInfo.DeclaringType == interfaceType) ? memberInfo.Name : memberInfo.DeclaringType.Name, paramName), ErrorNumbers.Error_CorrelationInvalid); 
                        error.UserData.Add(typeof(CorrelationParameterAttribute), (memberInfo.DeclaringType == interfaceType) ? memberInfo.Name : memberInfo.DeclaringType.Name);
                        validationErrors.Add(error); 
                    }
                    else if (paramTypes.ContainsKey(paramName) && (Type)paramTypes[paramName] != paramType)
                    {
                        // error parameter type mismatch 
                        ValidationError error = new ValidationError(SR.GetString(CultureInfo.CurrentCulture, SR.Error_CorrelationTypeNotConsistent, paramPath, typeof(CorrelationAliasAttribute).Name, (memberInfo.DeclaringType == interfaceType) ? memberInfo.Name : memberInfo.DeclaringType.Name, paramType.Name, ((Type)paramTypes[paramName]).Name, paramName, interfaceType.Name), ErrorNumbers.Error_CorrelationTypeNotConsistent);
                        error.UserData.Add(typeof(CorrelationAliasAttribute), (memberInfo.DeclaringType == interfaceType) ? memberInfo.Name : memberInfo.DeclaringType.Name); 
                        validationErrors.Add(error); 
                    }
                } 
            }

            if (initializerCount == 0)
            { 
                ValidationError error = new ValidationError(SR.GetString(CultureInfo.CurrentCulture,SR.Error_CorrelationInitializerNotDefinied, interfaceType.Name), ErrorNumbers.Error_CorrelationInitializerNotDefinied);
                error.UserData.Add(typeof(CorrelationInitializerAttribute), interfaceType.Name); 
                validationErrors.Add(error); 
            }
 
            return validationErrors;
        }

        private static ValidationErrorCollection ValidateInvalidHostInterfaceAttributes(Type interfaceType) 
        {
            if (interfaceType == null) 
                throw new ArgumentNullException("interfaceType"); 

            ValidationErrorCollection validationErrors = new ValidationErrorCollection(); 
            bool corrAttrsFound = false;
            foreach (MemberInfo memberInfo in interfaceType.GetMembers())
            {
                if (memberInfo.GetCustomAttributes(typeof(CorrelationInitializerAttribute), false).Length != 0 || 
                    memberInfo.GetCustomAttributes(typeof(CorrelationAliasAttribute), false).Length != 0)
                { 
                    corrAttrsFound = true; 
                    break;
                } 
            }

            if (corrAttrsFound)
            { 
                ValidationError error = new ValidationError(SR.GetString(CultureInfo.CurrentCulture, SR.Error_MissingCorrelationParameterAttribute, interfaceType.Name), ErrorNumbers.Error_MissingCorrelationParameterAttribute);
                error.UserData.Add(typeof(CorrelationParameterAttribute), interfaceType.Name); 
                validationErrors.Add(error); 
            }
 
            return validationErrors;
        }

        private static Type FetchParameterType(MemberInfo memberInfo, string paramPath) 
        {
            MethodInfo method = null; 
            if (memberInfo is EventInfo) 
            {
                Type delegateType = Helpers.GetDelegateFromEvent((EventInfo)memberInfo); 
                method = delegateType.GetMethod("Invoke");
            }
            else
                method = (MethodInfo)memberInfo; 

            return GetCorrelationParameterType(paramPath, method.GetParameters()); 
        } 

        private static void FillCorrelationAliasAttrs(MemberInfo memberInfo, Hashtable correlationAliasAttrs, ValidationErrorCollection validationErrors) 
        {
            foreach (object memberAttribute in memberInfo.GetCustomAttributes(typeof(CorrelationAliasAttribute), false))
            {
                CorrelationAliasAttribute aliasAttribute = Helpers.GetAttributeFromObject(memberAttribute); 
                // fill validation errors, name, path, duplicate check
                if (String.IsNullOrEmpty(aliasAttribute.Name) || aliasAttribute.Name.Trim().Length == 0) 
                { 
                    ValidationError error = new ValidationError(SR.GetString(CultureInfo.CurrentCulture,SR.Error_CorrelationAttributeInvalid, typeof(CorrelationAliasAttribute).Name, "Name", memberInfo.Name), ErrorNumbers.Error_CorrelationAttributeInvalid);
                    error.UserData.Add(typeof(CorrelationAliasAttribute), memberInfo.Name); 
                    validationErrors.Add(error);
                    continue;
                }
 
                if (String.IsNullOrEmpty(aliasAttribute.Path) || aliasAttribute.Path.Trim().Length == 0)
                { 
                    ValidationError error = new ValidationError(SR.GetString(CultureInfo.CurrentCulture,SR.Error_CorrelationAttributeInvalid, typeof(CorrelationAliasAttribute).Name, "Path", memberInfo.Name), ErrorNumbers.Error_CorrelationAttributeInvalid); 
                    error.UserData.Add(typeof(CorrelationAliasAttribute), memberInfo.Name);
                    validationErrors.Add(error); 
                    continue;
                }

                if (correlationAliasAttrs.Contains(aliasAttribute.Name)) 
                {
                    ValidationError error = new ValidationError(SR.GetString(CultureInfo.CurrentCulture,SR.Error_DuplicateCorrelationAttribute, typeof(CorrelationAliasAttribute).Name, aliasAttribute.Name, memberInfo.Name), ErrorNumbers.Error_DuplicateCorrelationAttribute); 
                    error.UserData.Add(typeof(CorrelationAliasAttribute), memberInfo.Name); 
                    validationErrors.Add(error);
                    continue; 
                }
                correlationAliasAttrs.Add(aliasAttribute.Name, aliasAttribute);
            }
 
            return;
        } 
 
        private static Type GetCorrelationParameterType(string parameterPropertyName, object parametersCollection)
        { 
            string[] parsedPropertyName = parameterPropertyName.Split('.');
            Type correlationParameterType = null;
            int index = 0;
 
            if (parsedPropertyName.Length == 1)
            { 
                Type evntHandlerType = null; 
                if (parametersCollection is CodeParameterDeclarationExpressionCollection)
                { 
                    foreach (CodeParameterDeclarationExpression parameterDeclaration in (CodeParameterDeclarationExpressionCollection)parametersCollection)
                    {
                        if (String.Compare("e", parameterDeclaration.Name, StringComparison.Ordinal) == 0)
                            evntHandlerType = parameterDeclaration.UserData[typeof(Type)] as Type; 
                    }
                } 
                else if (parametersCollection is ParameterInfo[]) 
                {
                    foreach (ParameterInfo parameterInfo in (ParameterInfo[])parametersCollection) 
                    {
                        if (String.Compare("e", parameterInfo.Name, StringComparison.Ordinal) == 0)
                            evntHandlerType = parameterInfo.ParameterType;
                    } 
                }
                if (evntHandlerType != null) 
                { 
                    string paramName = parsedPropertyName[0];
                    parsedPropertyName = new string[] { "e", paramName }; 
                }
            }

            if (parametersCollection is CodeParameterDeclarationExpressionCollection) 
            {
                foreach (CodeParameterDeclarationExpression parameterDeclaration in (CodeParameterDeclarationExpressionCollection)parametersCollection) 
                { 
                    if (String.Compare(parsedPropertyName[0], parameterDeclaration.Name, StringComparison.Ordinal) == 0)
                        correlationParameterType = parameterDeclaration.UserData[typeof(Type)] as Type; 
                }
            }
            else if (parametersCollection is ParameterInfo[])
            { 
                foreach (ParameterInfo parameterInfo in (ParameterInfo[])parametersCollection)
                { 
                    if (String.Compare(parsedPropertyName[0], parameterInfo.Name, StringComparison.Ordinal) == 0) 
                        correlationParameterType = parameterInfo.ParameterType;
                } 
            }
            else
                return null;
 
            if (parsedPropertyName.Length == 1)
                return correlationParameterType; 
 
            //Search each part of the parsed name in it's predecessor's public properties/fields
            for (index = 1; index < parsedPropertyName.Length && correlationParameterType != null; index++) 
            {
                Type tempParameterType = null;

                //Search though the public properties for a matching name 
                PropertyInfo[] publicProperties = correlationParameterType.GetProperties();
                foreach (PropertyInfo propertyInfo in publicProperties) 
                { 
                    tempParameterType = null;
                    if (String.Compare(propertyInfo.Name, parsedPropertyName[index], StringComparison.Ordinal) == 0) 
                    {
                        tempParameterType = propertyInfo.PropertyType;
                        break;
                    } 
                }
 
                if (tempParameterType != null) 
                {
                    correlationParameterType = tempParameterType; 
                    continue;
                }

                //Search though the public fields for a matching name 
                FieldInfo[] publicFields = correlationParameterType.GetFields();
                foreach (FieldInfo fieldInfo in publicFields) 
                { 
                    tempParameterType = null;
                    if (String.Compare(fieldInfo.Name, parsedPropertyName[index], StringComparison.Ordinal) == 0) 
                    {
                        tempParameterType = fieldInfo.FieldType;
                        break;
                    } 
                }
 
                if (tempParameterType != null) 
                {
                    correlationParameterType = tempParameterType; 
                    continue;
                }

                // If a matching public field or property was not found, return null. 
                if (tempParameterType == null)
                    return null; 
            } 

            if (index == parsedPropertyName.Length) 
                return correlationParameterType;

            return null;
        } 
    }
 
    internal static class ParameterBindingValidator 
    {
        internal static ValidationErrorCollection Validate(ValidationManager manager, Object obj) 
        {
            ValidationErrorCollection validationErrors = new ValidationErrorCollection();

            Activity activity = obj as Activity; 
            if (!(activity is CallExternalMethodActivity) && !(activity is HandleExternalEventActivity))
                throw new ArgumentException(SR.GetString(SR.Error_UnexpectedArgumentType, typeof(Activity).FullName), "obj"); 
 
            Type interfaceType = (activity is CallExternalMethodActivity) ? ((CallExternalMethodActivity)activity).InterfaceType : ((HandleExternalEventActivity)activity).InterfaceType;
            if (interfaceType == null) 
                return validationErrors;

            string operation = (activity is CallExternalMethodActivity) ? ((CallExternalMethodActivity)activity).MethodName : ((HandleExternalEventActivity)activity).EventName;
            if (String.IsNullOrEmpty(operation)) 
                return validationErrors;
 
            WorkflowParameterBindingCollection parameterBinding = (activity is CallExternalMethodActivity) ? ((CallExternalMethodActivity)activity).ParameterBindings : ((HandleExternalEventActivity)activity).ParameterBindings; 

            MethodInfo mInfo = interfaceType.GetMethod(operation); 
            if (mInfo == null)
            {
                if (activity is CallExternalMethodActivity)
                { 
                     return validationErrors;
                } 
            } 
            bool isEvent = false;
            if (mInfo == null) 
            {
                //This is a work around for delgates of unbounded generic type. There is no support
                //in file code model for these so we dont support it for now. The only way
                //to detect if the DesignTimeEventInfo has EventHandler of unbounded generic type 
                //is to check if we get the methods correctly here Ref Bug#17783
                EventInfo eventInfo = interfaceType.GetEvent(operation); 
                if (eventInfo == null || eventInfo.GetAddMethod(true) == null) 
                {
                     return validationErrors; 
                }

                Type delegateType = eventInfo.EventHandlerType;
                if (delegateType == null) 
                    delegateType = TypeProvider.GetEventHandlerType(eventInfo);
 
                mInfo = delegateType.GetMethod("Invoke"); 
                isEvent = true;
            } 

            ValidateParameterBinding(manager, activity, isEvent, operation, mInfo, parameterBinding, validationErrors);
            return validationErrors;
        } 

        private static void ValidateParameterBinding(ValidationManager manager, Activity activity, bool isEvent, string operation, MethodInfo mInfo, WorkflowParameterBindingCollection parameterBindings, ValidationErrorCollection validationErrors) 
        { 
            Hashtable parameterCollection = new Hashtable();
            ParameterInfo[] parameters = mInfo.GetParameters(); 
            bool canBeIntercepted = false;

            foreach (ParameterInfo parameter in parameters)
            { 
                if (TypeProvider.IsAssignable(typeof(ExternalDataEventArgs),parameter.ParameterType))
                { 
                    if (parameter.Position == 1) 
                        canBeIntercepted = true;
                    ValidateParameterSerializabiltiy(validationErrors, parameter.ParameterType); 
                }
                parameterCollection.Add(parameter.Name, parameter);
            }
 
            if(isEvent && (!canBeIntercepted || parameters.Length != 2))
                validationErrors.Add(new ValidationError(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_InvalidEventArgsSignature, operation)), ErrorNumbers.Error_FieldNotExists, false, "EventName")); 
 
            if (mInfo.ReturnType != typeof(void))
                parameterCollection.Add("(ReturnValue)", mInfo.ReturnParameter); 

            foreach (WorkflowParameterBinding parameterBinding in parameterBindings)
            {
                string paramName = parameterBinding.ParameterName; 
                if (!parameterCollection.ContainsKey(paramName))
                { 
                    if (isEvent) 
                        validationErrors.Add(new ValidationError(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_InvalidEventPropertyName, paramName)), ErrorNumbers.Error_FieldNotExists, false, "ParameterBindings"));
                    else 
                        validationErrors.Add(new ValidationError(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_InvalidMethodPropertyName, paramName)), ErrorNumbers.Error_FieldNotExists, false, "ParameterBindings"));
                    continue;
                }
 
                object paramValue = null;
                if (parameterBinding.IsBindingSet(WorkflowParameterBinding.ValueProperty)) 
                    paramValue = parameterBinding.GetBinding(WorkflowParameterBinding.ValueProperty); 
                else
                    paramValue = parameterBinding.GetValue(WorkflowParameterBinding.ValueProperty); 

                if (paramValue == null)
                    continue;
 
                ParameterInfo paramInfo = parameterCollection[paramName] as ParameterInfo;
                if (paramInfo != null) 
                { 
                    AccessTypes access = AccessTypes.Read;
                    if (paramInfo.IsOut || paramInfo.IsRetval) 
                        access = AccessTypes.Write;
                    else if (paramInfo.ParameterType.IsByRef)
                        access |= AccessTypes.Write;
 
                    ValidationErrorCollection variableErrors = ValidationHelpers.ValidateProperty(manager, activity, paramValue,
                                                                                                  new PropertyValidationContext(parameterBinding, null, paramName), 
                                                                                                  new BindValidationContext(paramInfo.ParameterType.IsByRef ? paramInfo.ParameterType.GetElementType() : paramInfo.ParameterType, access)); 
                    validationErrors.AddRange(variableErrors);
                } 
            }
        }

        private static void ValidateParameterSerializabiltiy(ValidationErrorCollection validationErrors, Type type) 
        {
            object[] attrs = type.GetCustomAttributes(typeof(SerializableAttribute), false); 
            Type serializableType = type.GetInterface(typeof(ISerializable).FullName); 
            if (attrs.Length  == 0 && serializableType == null)
            { 
                validationErrors.Add(new ValidationError(string.Format(CultureInfo.CurrentCulture,
                                     SR.GetString(SR.Error_EventArgumentValidationException), type.FullName),
                                     ErrorNumbers.Error_FieldNotExists, false, "EventName"));
            } 

 
        } 
    }
 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK