// 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)); } } }
// 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) { var returnEarly = false; var oldMethodExecutor = methodExecutor; methodExecutor = null; if (string.IsNullOrEmpty(this.MethodName)) { metadata.AddValidationError(SR.ActivityPropertyMustBeSet("MethodName", this.Parent.DisplayName)); returnEarly = true; } var 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. var bindingFlags = this.TargetType != null ? staticBindingFlags : instanceBindingFlags; var 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 var parameterTypes = Parameters.Select(argument => argument.Direction == ArgumentDirection.In ? argument.ArgumentType : argument.ArgumentType.MakeByRefType()) .ToArray(); var genericTypeArguments = this.GenericTypeArguments.ToArray(); var 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. var resultType = this.ResultType; if (this.RunAsynchronously) { var formalParamCount = parameterTypes.Length; var beginMethodParameterTypes = new Type[formalParamCount + 2]; for (var 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)); } } }