// returns null MethodInfo on failure
        private MethodInfo Resolve(Type targetType, string methodName, BindingFlags bindingFlags,
                                   InheritanceAndParamArrayAwareBinder methodBinder, Type[] parameterTypes, Type[] genericTypeArguments, bool suppressAmbiguityException)
        {
            MethodInfo method;

            try
            {
                methodBinder.SelectMethodCalled = false;
                method = targetType.GetMethod(methodName, bindingFlags,
                                              methodBinder, CallingConventions.Any, parameterTypes, null);
            }
            catch (AmbiguousMatchException)
            {
                if (suppressAmbiguityException) // For Begin/End methods, ambiguity just means no match
                {
                    return(null);
                }
                else // For a regular sync method, ambiguity is distinct from no match and gets an explicit error message
                {
                    throw;
                }
            }

            if (method != null && !methodBinder.SelectMethodCalled && genericTypeArguments.Length > 0)
            // methodBinder is only used when there's more than one possible match, so method might still be generic
            {
                method = Instantiate(method, genericTypeArguments); // if it fails because of e.g. constraints it will just become null
            }
            return(method);
        }
Exemplo n.º 2
0
        // returns null MethodInfo on failure
        MethodInfo Resolve(Type targetType, string methodName, BindingFlags bindingFlags,
            InheritanceAndParamArrayAwareBinder methodBinder, Type[] parameterTypes, Type[] genericTypeArguments, bool suppressAmbiguityException)
        {
            MethodInfo method;
            try
            {
                methodBinder.SelectMethodCalled = false;
                method = targetType.GetMethod(methodName, bindingFlags,
                    methodBinder, CallingConventions.Any, parameterTypes, null);
            }
            catch (AmbiguousMatchException)
            {
                if (suppressAmbiguityException) // For Begin/End methods, ambiguity just means no match
                {
                    return null;
                }
                else // For a regular sync method, ambiguity is distinct from no match and gets an explicit error message
                {
                    throw;
                }
            }

            if (method != null && !methodBinder.SelectMethodCalled && genericTypeArguments.Length > 0)
            // methodBinder is only used when there's more than one possible match, so method might still be generic
            {
                method = Instantiate(method, genericTypeArguments); // if it fails because of e.g. constraints it will just become null
            }
            return method;
        }
        // Set methodExecutor, returning an error string if there are any problems (ambiguous match, etc.).
        public void DetermineMethodInfo(CodeActivityMetadata metadata, MruCache <MethodInfo, Func <object, object[], object> > funcCache, ReaderWriterLockSlim locker,
                                        ref MethodExecutor methodExecutor)
        {
            bool returnEarly = false;

            MethodExecutor oldMethodExecutor = methodExecutor;

            methodExecutor = null;
            if (string.IsNullOrEmpty(this.MethodName))
            {
                metadata.AddValidationError(SR.ActivityPropertyMustBeSet("MethodName", this.Parent.DisplayName));
                returnEarly = true;
            }

            Type targetType = this.TargetType;

            // If TargetType and the type of TargetObject are both set, it's an error.
            if (targetType != null && this.TargetObject != null && !this.TargetObject.IsEmpty)
            {
                metadata.AddValidationError(SR.TargetTypeAndTargetObjectAreMutuallyExclusive(this.Parent.GetType().Name, this.Parent.DisplayName));
                returnEarly = true;
            }

            // If TargetType was set, look for a static method. If TargetObject was set, look for an instance method. They can't both be set.
            BindingFlags bindingFlags = this.TargetType != null ? staticBindingFlags : instanceBindingFlags;
            string       bindingType  = bindingFlags == staticBindingFlags ? staticString : instanceString;

            if (targetType == null)
            {
                if (this.TargetObject != null && !this.TargetObject.IsEmpty)
                {
                    targetType = this.TargetObject.ArgumentType;
                }
                else
                {
                    metadata.AddValidationError(SR.OneOfTwoPropertiesMustBeSet("TargetObject", "TargetType", this.Parent.GetType().Name, this.Parent.DisplayName));
                    returnEarly = true;
                }
            }

            // We've had one or more constraint violations already
            if (returnEarly)
            {
                return;
            }

            // Convert OutArgs and InOutArgs to out/ref types before resolution
            Type[] parameterTypes =
                Parameters.Select(argument => argument.Direction == ArgumentDirection.In ? argument.ArgumentType : argument.ArgumentType.MakeByRefType())
                .ToArray();

            Type[] genericTypeArguments = this.GenericTypeArguments.ToArray();

            InheritanceAndParamArrayAwareBinder methodBinder = new InheritanceAndParamArrayAwareBinder(targetType, genericTypeArguments, this.Parent);

            // It may be possible to know (and check) the resultType even if the result won't be assigned anywhere.
            // Used 1.) for detecting async pattern, and 2.) to make sure we selected the correct MethodInfo.
            Type resultType = this.ResultType;

            if (this.RunAsynchronously)
            {
                int    formalParamCount          = parameterTypes.Length;
                Type[] beginMethodParameterTypes = new Type[formalParamCount + 2];
                for (int i = 0; i < formalParamCount; i++)
                {
                    beginMethodParameterTypes[i] = parameterTypes[i];
                }
                beginMethodParameterTypes[formalParamCount]     = typeof(AsyncCallback);
                beginMethodParameterTypes[formalParamCount + 1] = typeof(object);

                Type[] endMethodParameterTypes = { typeof(IAsyncResult) };

                this.beginMethod = Resolve(targetType, "Begin" + this.MethodName, bindingFlags,
                                           methodBinder, beginMethodParameterTypes, genericTypeArguments, true);
                if (this.beginMethod != null && !this.beginMethod.ReturnType.Equals(typeof(IAsyncResult)))
                {
                    this.beginMethod = null;
                }
                this.endMethod = Resolve(targetType, "End" + this.MethodName, bindingFlags,
                                         methodBinder, endMethodParameterTypes, genericTypeArguments, true);
                if (this.endMethod != null && resultType != null && !TypeHelper.AreTypesCompatible(this.endMethod.ReturnType, resultType))
                {
                    metadata.AddValidationError(SR.ReturnTypeIncompatible(this.endMethod.ReturnType.Name, MethodName, targetType.Name, this.Parent.DisplayName, resultType.Name));
                    this.endMethod = null;
                    return;
                }

                if (this.beginMethod != null && this.endMethod != null && this.beginMethod.IsStatic == this.endMethod.IsStatic)
                {
                    if (!(oldMethodExecutor is AsyncPatternMethodExecutor) ||
                        !((AsyncPatternMethodExecutor)oldMethodExecutor).IsTheSame(this.beginMethod, this.endMethod))
                    {
                        methodExecutor = new AsyncPatternMethodExecutor(metadata, this.beginMethod, this.endMethod, this.Parent,
                                                                        this.TargetType, this.TargetObject, this.Parameters, this.Result, funcCache, locker);
                    }
                    else
                    {
                        methodExecutor = new AsyncPatternMethodExecutor((AsyncPatternMethodExecutor)oldMethodExecutor,
                                                                        this.TargetType, this.TargetObject, this.Parameters, this.Result);
                    }
                    return;
                }
            }

            MethodInfo result;

            try
            {
                result = Resolve(targetType, this.MethodName, bindingFlags,
                                 methodBinder, parameterTypes, genericTypeArguments, false);
            }
            catch (AmbiguousMatchException)
            {
                metadata.AddValidationError(SR.DuplicateMethodFound(targetType.Name, bindingType, MethodName, this.Parent.DisplayName));
                return;
            }

            if (result == null)
            {
                metadata.AddValidationError(SR.PublicMethodWithMatchingParameterDoesNotExist(targetType.Name, bindingType, MethodName, this.Parent.DisplayName));
                return;
            }
            else if (resultType != null && !TypeHelper.AreTypesCompatible(result.ReturnType, resultType))
            {
                metadata.AddValidationError(
                    SR.ReturnTypeIncompatible(result.ReturnType.Name, MethodName,
                                              targetType.Name, this.Parent.DisplayName, resultType.Name));
                return;
            }
            else
            {
                this.syncMethod = result;
                if (this.RunAsynchronously)
                {
                    if (!(oldMethodExecutor is AsyncWaitCallbackMethodExecutor) ||
                        !((AsyncWaitCallbackMethodExecutor)oldMethodExecutor).IsTheSame(this.syncMethod))
                    {
                        methodExecutor = new AsyncWaitCallbackMethodExecutor(metadata, this.syncMethod, this.Parent,
                                                                             this.TargetType, this.TargetObject, this.Parameters, this.Result, funcCache, locker);
                    }
                    else
                    {
                        methodExecutor = new AsyncWaitCallbackMethodExecutor((AsyncWaitCallbackMethodExecutor)oldMethodExecutor,
                                                                             this.TargetType, this.TargetObject, this.Parameters, this.Result);
                    }
                }
                else if (!(oldMethodExecutor is SyncMethodExecutor) ||
                         !((SyncMethodExecutor)oldMethodExecutor).IsTheSame(this.syncMethod))
                {
                    methodExecutor = new SyncMethodExecutor(metadata, this.syncMethod, this.Parent, this.TargetType,
                                                            this.TargetObject, this.Parameters, this.Result, funcCache, locker);
                }
                else
                {
                    methodExecutor = new SyncMethodExecutor((SyncMethodExecutor)oldMethodExecutor, this.TargetType,
                                                            this.TargetObject, this.Parameters, this.Result);
                }
            }
        }
Exemplo n.º 4
0
        // Set methodExecutor, returning an error string if there are any problems (ambiguous match, etc.).
        public void DetermineMethodInfo(CodeActivityMetadata metadata, MruCache<MethodInfo, Func<object, object[], object>> funcCache, ReaderWriterLockSlim locker, 
            ref MethodExecutor methodExecutor)
        {
            bool returnEarly = false;

            MethodExecutor oldMethodExecutor = methodExecutor;
            methodExecutor = null;
            if (string.IsNullOrEmpty(this.MethodName))
            {
                metadata.AddValidationError(SR.ActivityPropertyMustBeSet("MethodName", this.Parent.DisplayName));
                returnEarly = true;
            }

            Type targetType = this.TargetType;

            // If TargetType and the type of TargetObject are both set, it's an error.
            if (targetType != null && this.TargetObject != null && !this.TargetObject.IsEmpty)
            {
                metadata.AddValidationError(SR.TargetTypeAndTargetObjectAreMutuallyExclusive(this.Parent.GetType().Name, this.Parent.DisplayName));
                returnEarly = true;
            }

            // If TargetType was set, look for a static method. If TargetObject was set, look for an instance method. They can't both be set.
            BindingFlags bindingFlags = this.TargetType != null ? staticBindingFlags : instanceBindingFlags;
            string bindingType = bindingFlags == staticBindingFlags ? staticString : instanceString;

            if (targetType == null)
            {
                if (this.TargetObject != null && !this.TargetObject.IsEmpty)
                {
                    targetType = this.TargetObject.ArgumentType;
                }
                else
                {
                    metadata.AddValidationError(SR.OneOfTwoPropertiesMustBeSet("TargetObject", "TargetType", this.Parent.GetType().Name, this.Parent.DisplayName));
                    returnEarly = true;
                }
            }

            // We've had one or more constraint violations already
            if (returnEarly)
            {
                return;
            }

            // Convert OutArgs and InOutArgs to out/ref types before resolution
            Type[] parameterTypes =
                Parameters.Select(argument => argument.Direction == ArgumentDirection.In ? argument.ArgumentType : argument.ArgumentType.MakeByRefType())
                    .ToArray();

            Type[] genericTypeArguments = this.GenericTypeArguments.ToArray();

            InheritanceAndParamArrayAwareBinder methodBinder = new InheritanceAndParamArrayAwareBinder(targetType, genericTypeArguments, this.Parent);

            // It may be possible to know (and check) the resultType even if the result won't be assigned anywhere.     
            // Used 1.) for detecting async pattern, and 2.) to make sure we selected the correct MethodInfo.
            Type resultType = this.ResultType;

            if (this.RunAsynchronously)
            {
                int formalParamCount = parameterTypes.Length;
                Type[] beginMethodParameterTypes = new Type[formalParamCount + 2];
                for (int i = 0; i < formalParamCount; i++)
                {
                    beginMethodParameterTypes[i] = parameterTypes[i];
                }
                beginMethodParameterTypes[formalParamCount] = typeof(AsyncCallback);
                beginMethodParameterTypes[formalParamCount + 1] = typeof(object);

                Type[] endMethodParameterTypes = { typeof(IAsyncResult) };

                this.beginMethod = Resolve(targetType, "Begin" + this.MethodName, bindingFlags,
                    methodBinder, beginMethodParameterTypes, genericTypeArguments, true);
                if (this.beginMethod != null && !this.beginMethod.ReturnType.Equals(typeof(IAsyncResult)))
                {
                    this.beginMethod = null;
                }
                this.endMethod = Resolve(targetType, "End" + this.MethodName, bindingFlags,
                    methodBinder, endMethodParameterTypes, genericTypeArguments, true);
                if (this.endMethod != null && resultType != null && !TypeHelper.AreTypesCompatible(this.endMethod.ReturnType, resultType))
                {
                    metadata.AddValidationError(SR.ReturnTypeIncompatible(this.endMethod.ReturnType.Name, MethodName, targetType.Name, this.Parent.DisplayName, resultType.Name));
                    this.endMethod = null;
                    return;
                }

                if (this.beginMethod != null && this.endMethod != null && this.beginMethod.IsStatic == this.endMethod.IsStatic)
                {
                    if (!(oldMethodExecutor is AsyncPatternMethodExecutor) ||
                        !((AsyncPatternMethodExecutor)oldMethodExecutor).IsTheSame(this.beginMethod, this.endMethod))
                    {
                        methodExecutor = new AsyncPatternMethodExecutor(metadata, this.beginMethod, this.endMethod, this.Parent, 
                            this.TargetType, this.TargetObject, this.Parameters, this.Result, funcCache, locker);
                    }
                    else
                    {
                        methodExecutor = new AsyncPatternMethodExecutor((AsyncPatternMethodExecutor)oldMethodExecutor, 
                            this.TargetType, this.TargetObject, this.Parameters, this.Result);
                    }
                    return;
                }
            }

            MethodInfo result;
            try
            {
                result = Resolve(targetType, this.MethodName, bindingFlags,
                    methodBinder, parameterTypes, genericTypeArguments, false);
            }
            catch (AmbiguousMatchException)
            {
                metadata.AddValidationError(SR.DuplicateMethodFound(targetType.Name, bindingType, MethodName, this.Parent.DisplayName));
                return;
            }

            if (result == null)
            {
                metadata.AddValidationError(SR.PublicMethodWithMatchingParameterDoesNotExist(targetType.Name, bindingType, MethodName, this.Parent.DisplayName));
                return;
            }
            else if (resultType != null && !TypeHelper.AreTypesCompatible(result.ReturnType, resultType))
            {
                metadata.AddValidationError(
                    SR.ReturnTypeIncompatible(result.ReturnType.Name, MethodName,
                        targetType.Name, this.Parent.DisplayName, resultType.Name));
                return;
            }
            else
            {
                this.syncMethod = result;
                if (this.RunAsynchronously)
                {
                    if (!(oldMethodExecutor is AsyncWaitCallbackMethodExecutor) ||
                        !((AsyncWaitCallbackMethodExecutor)oldMethodExecutor).IsTheSame(this.syncMethod))
                    {
                        methodExecutor = new AsyncWaitCallbackMethodExecutor(metadata, this.syncMethod, this.Parent, 
                            this.TargetType, this.TargetObject, this.Parameters, this.Result, funcCache, locker);
                    }
                    else
                    {
                        methodExecutor = new AsyncWaitCallbackMethodExecutor((AsyncWaitCallbackMethodExecutor)oldMethodExecutor,
                            this.TargetType, this.TargetObject, this.Parameters, this.Result);
                    }

                }
                else if (!(oldMethodExecutor is SyncMethodExecutor) ||
                    !((SyncMethodExecutor)oldMethodExecutor).IsTheSame(this.syncMethod))
                {
                    methodExecutor = new SyncMethodExecutor(metadata, this.syncMethod, this.Parent, this.TargetType,
                        this.TargetObject, this.Parameters, this.Result, funcCache, locker);
                }
                else
                {
                    methodExecutor = new SyncMethodExecutor((SyncMethodExecutor)oldMethodExecutor, this.TargetType,
                        this.TargetObject, this.Parameters, this.Result);
                }

            }
        }
 public void DetermineMethodInfo(CodeActivityMetadata metadata, out MethodExecutor methodExecutor)
 {
     bool flag = false;
     methodExecutor = null;
     if (string.IsNullOrEmpty(this.MethodName))
     {
         metadata.AddValidationError(System.Activities.SR.ActivityPropertyMustBeSet("MethodName", this.Parent.DisplayName));
         flag = true;
     }
     Type targetType = this.TargetType;
     if (((targetType != null) && (this.TargetObject != null)) && !this.TargetObject.IsEmpty)
     {
         metadata.AddValidationError(System.Activities.SR.TargetTypeAndTargetObjectAreMutuallyExclusive(this.Parent.GetType().Name, this.Parent.DisplayName));
         flag = true;
     }
     BindingFlags bindingFlags = (this.TargetType != null) ? staticBindingFlags : instanceBindingFlags;
     string str = (bindingFlags == staticBindingFlags) ? staticString : instanceString;
     if (targetType == null)
     {
         if ((this.TargetObject != null) && !this.TargetObject.IsEmpty)
         {
             targetType = this.TargetObject.ArgumentType;
         }
         else
         {
             metadata.AddValidationError(System.Activities.SR.OneOfTwoPropertiesMustBeSet("TargetObject", "TargetType", this.Parent.GetType().Name, this.Parent.DisplayName));
             flag = true;
         }
     }
     if (!flag)
     {
         MethodInfo info;
         Type[] parameterTypes = this.Parameters.Select<Argument, Type>(delegate (Argument argument) {
             if (argument.Direction != ArgumentDirection.In)
             {
                 return argument.ArgumentType.MakeByRefType();
             }
             return argument.ArgumentType;
         }).ToArray<Type>();
         Type[] genericTypeArguments = this.GenericTypeArguments.ToArray<Type>();
         InheritanceAndParamArrayAwareBinder methodBinder = new InheritanceAndParamArrayAwareBinder(targetType, genericTypeArguments, this.Parent);
         Type resultType = this.ResultType;
         if (this.RunAsynchronously)
         {
             int length = parameterTypes.Length;
             Type[] typeArray3 = new Type[length + 2];
             for (int i = 0; i < length; i++)
             {
                 typeArray3[i] = parameterTypes[i];
             }
             typeArray3[length] = typeof(AsyncCallback);
             typeArray3[length + 1] = typeof(object);
             Type[] typeArray4 = new Type[] { typeof(IAsyncResult) };
             this.beginMethod = this.Resolve(targetType, "Begin" + this.MethodName, bindingFlags, methodBinder, typeArray3, genericTypeArguments, true);
             if ((this.beginMethod != null) && !this.beginMethod.ReturnType.Equals(typeof(IAsyncResult)))
             {
                 this.beginMethod = null;
             }
             this.endMethod = this.Resolve(targetType, "End" + this.MethodName, bindingFlags, methodBinder, typeArray4, genericTypeArguments, true);
             if (((this.endMethod != null) && (resultType != null)) && !System.Runtime.TypeHelper.AreTypesCompatible(this.endMethod.ReturnType, resultType))
             {
                 this.endMethod = null;
                 metadata.AddValidationError(System.Activities.SR.ReturnTypeIncompatible(this.endMethod.ReturnType.Name, this.MethodName, targetType.Name, this.Parent.DisplayName, resultType.Name));
                 return;
             }
             if (((this.beginMethod != null) && (this.endMethod != null)) && (this.beginMethod.IsStatic == this.endMethod.IsStatic))
             {
                 methodExecutor = new AsyncPatternMethodExecutor(this.beginMethod, this.endMethod, this.Parent, this.TargetType, this.TargetObject, this.Parameters, this.Result);
                 return;
             }
         }
         try
         {
             info = this.Resolve(targetType, this.MethodName, bindingFlags, methodBinder, parameterTypes, genericTypeArguments, false);
         }
         catch (AmbiguousMatchException)
         {
             metadata.AddValidationError(System.Activities.SR.DuplicateMethodFound(targetType.Name, str, this.MethodName, this.Parent.DisplayName));
             return;
         }
         if (info != null)
         {
             if ((resultType != null) && !System.Runtime.TypeHelper.AreTypesCompatible(info.ReturnType, resultType))
             {
                 metadata.AddValidationError(System.Activities.SR.ReturnTypeIncompatible(info.ReturnType.Name, this.MethodName, targetType.Name, this.Parent.DisplayName, resultType.Name));
             }
             else
             {
                 this.syncMethod = info;
                 if (this.RunAsynchronously)
                 {
                     methodExecutor = new AsyncWaitCallbackMethodExecutor(info, this.Parent, this.TargetType, this.TargetObject, this.Parameters, this.Result);
                 }
                 else
                 {
                     methodExecutor = new SyncMethodExecutor(info, this.Parent, this.TargetType, this.TargetObject, this.Parameters, this.Result);
                 }
             }
         }
         else
         {
             metadata.AddValidationError(System.Activities.SR.PublicMethodWithMatchingParameterDoesNotExist(targetType.Name, str, this.MethodName, this.Parent.DisplayName));
         }
     }
 }
 private MethodInfo Resolve(Type targetType, string methodName, BindingFlags bindingFlags, InheritanceAndParamArrayAwareBinder methodBinder, Type[] parameterTypes, Type[] genericTypeArguments, bool suppressAmbiguityException)
 {
     MethodInfo info;
     try
     {
         methodBinder.SelectMethodCalled = false;
         info = targetType.GetMethod(methodName, bindingFlags, methodBinder, CallingConventions.Any, parameterTypes, null);
     }
     catch (AmbiguousMatchException)
     {
         if (!suppressAmbiguityException)
         {
             throw;
         }
         return null;
     }
     if (((info != null) && !methodBinder.SelectMethodCalled) && (genericTypeArguments.Length > 0))
     {
         info = Instantiate(info, genericTypeArguments);
     }
     return info;
 }
        public void DetermineMethodInfo(CodeActivityMetadata metadata, out MethodExecutor methodExecutor)
        {
            bool flag = false;

            methodExecutor = null;
            if (string.IsNullOrEmpty(this.MethodName))
            {
                metadata.AddValidationError(System.Activities.SR.ActivityPropertyMustBeSet("MethodName", this.Parent.DisplayName));
                flag = true;
            }
            Type targetType = this.TargetType;

            if (((targetType != null) && (this.TargetObject != null)) && !this.TargetObject.IsEmpty)
            {
                metadata.AddValidationError(System.Activities.SR.TargetTypeAndTargetObjectAreMutuallyExclusive(this.Parent.GetType().Name, this.Parent.DisplayName));
                flag = true;
            }
            BindingFlags bindingFlags = (this.TargetType != null) ? staticBindingFlags : instanceBindingFlags;
            string       str          = (bindingFlags == staticBindingFlags) ? staticString : instanceString;

            if (targetType == null)
            {
                if ((this.TargetObject != null) && !this.TargetObject.IsEmpty)
                {
                    targetType = this.TargetObject.ArgumentType;
                }
                else
                {
                    metadata.AddValidationError(System.Activities.SR.OneOfTwoPropertiesMustBeSet("TargetObject", "TargetType", this.Parent.GetType().Name, this.Parent.DisplayName));
                    flag = true;
                }
            }
            if (!flag)
            {
                MethodInfo info;
                Type[]     parameterTypes = this.Parameters.Select <Argument, Type>(delegate(Argument argument) {
                    if (argument.Direction != ArgumentDirection.In)
                    {
                        return(argument.ArgumentType.MakeByRefType());
                    }
                    return(argument.ArgumentType);
                }).ToArray <Type>();
                Type[] genericTypeArguments = this.GenericTypeArguments.ToArray <Type>();
                InheritanceAndParamArrayAwareBinder methodBinder = new InheritanceAndParamArrayAwareBinder(targetType, genericTypeArguments, this.Parent);
                Type resultType = this.ResultType;
                if (this.RunAsynchronously)
                {
                    int    length     = parameterTypes.Length;
                    Type[] typeArray3 = new Type[length + 2];
                    for (int i = 0; i < length; i++)
                    {
                        typeArray3[i] = parameterTypes[i];
                    }
                    typeArray3[length]     = typeof(AsyncCallback);
                    typeArray3[length + 1] = typeof(object);
                    Type[] typeArray4 = new Type[] { typeof(IAsyncResult) };
                    this.beginMethod = this.Resolve(targetType, "Begin" + this.MethodName, bindingFlags, methodBinder, typeArray3, genericTypeArguments, true);
                    if ((this.beginMethod != null) && !this.beginMethod.ReturnType.Equals(typeof(IAsyncResult)))
                    {
                        this.beginMethod = null;
                    }
                    this.endMethod = this.Resolve(targetType, "End" + this.MethodName, bindingFlags, methodBinder, typeArray4, genericTypeArguments, true);
                    if (((this.endMethod != null) && (resultType != null)) && !System.Runtime.TypeHelper.AreTypesCompatible(this.endMethod.ReturnType, resultType))
                    {
                        this.endMethod = null;
                        metadata.AddValidationError(System.Activities.SR.ReturnTypeIncompatible(this.endMethod.ReturnType.Name, this.MethodName, targetType.Name, this.Parent.DisplayName, resultType.Name));
                        return;
                    }
                    if (((this.beginMethod != null) && (this.endMethod != null)) && (this.beginMethod.IsStatic == this.endMethod.IsStatic))
                    {
                        methodExecutor = new AsyncPatternMethodExecutor(this.beginMethod, this.endMethod, this.Parent, this.TargetType, this.TargetObject, this.Parameters, this.Result);
                        return;
                    }
                }
                try
                {
                    info = this.Resolve(targetType, this.MethodName, bindingFlags, methodBinder, parameterTypes, genericTypeArguments, false);
                }
                catch (AmbiguousMatchException)
                {
                    metadata.AddValidationError(System.Activities.SR.DuplicateMethodFound(targetType.Name, str, this.MethodName, this.Parent.DisplayName));
                    return;
                }
                if (info != null)
                {
                    if ((resultType != null) && !System.Runtime.TypeHelper.AreTypesCompatible(info.ReturnType, resultType))
                    {
                        metadata.AddValidationError(System.Activities.SR.ReturnTypeIncompatible(info.ReturnType.Name, this.MethodName, targetType.Name, this.Parent.DisplayName, resultType.Name));
                    }
                    else
                    {
                        this.syncMethod = info;
                        if (this.RunAsynchronously)
                        {
                            methodExecutor = new AsyncWaitCallbackMethodExecutor(info, this.Parent, this.TargetType, this.TargetObject, this.Parameters, this.Result);
                        }
                        else
                        {
                            methodExecutor = new SyncMethodExecutor(info, this.Parent, this.TargetType, this.TargetObject, this.Parameters, this.Result);
                        }
                    }
                }
                else
                {
                    metadata.AddValidationError(System.Activities.SR.PublicMethodWithMatchingParameterDoesNotExist(targetType.Name, str, this.MethodName, this.Parent.DisplayName));
                }
            }
        }
        private MethodInfo Resolve(Type targetType, string methodName, BindingFlags bindingFlags, InheritanceAndParamArrayAwareBinder methodBinder, Type[] parameterTypes, Type[] genericTypeArguments, bool suppressAmbiguityException)
        {
            MethodInfo info;

            try
            {
                methodBinder.SelectMethodCalled = false;
                info = targetType.GetMethod(methodName, bindingFlags, methodBinder, CallingConventions.Any, parameterTypes, null);
            }
            catch (AmbiguousMatchException)
            {
                if (!suppressAmbiguityException)
                {
                    throw;
                }
                return(null);
            }
            if (((info != null) && !methodBinder.SelectMethodCalled) && (genericTypeArguments.Length > 0))
            {
                info = Instantiate(info, genericTypeArguments);
            }
            return(info);
        }