MethodResolver.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 / NetFx40 / System.Activities / System / Activities / Statements / MethodResolver.cs / 1305376 / MethodResolver.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------

namespace System.Activities.Statements 
{
    using System.Collections.Generic; 
    using System.Collections.ObjectModel; 
    using System.Globalization;
    using System.Linq; 
    using System.Reflection;
    using System.Runtime;

    // Helper class for InvokeMethod. 
    // Factory for MethodExecutor strategies. Conceptually, resolves to the correct MethodInfo based on target type,
    // method name, parameters, and async flags + availability of Begin/End paired methods of the correct static-ness. 
    sealed class MethodResolver 
    {
 
        static readonly BindingFlags staticBindingFlags = BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static;
        static readonly BindingFlags instanceBindingFlags = BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance;
        static readonly string staticString = "static";     // Used in error messages below. Technical term, not localizable.
        static readonly string instanceString = "instance"; // Used in error messages below. Technical term, not localizable. 
        MethodInfo syncMethod;
        MethodInfo beginMethod; 
        MethodInfo endMethod; 

        public MethodResolver() 
        {
        }

        public Collection GenericTypeArguments { get; set; } 

        public string MethodName { get; set; } 
 
        public Collection Parameters { get; set; }
 
        public RuntimeArgument Result { get; set; }

        public InArgument TargetObject { get; set; }
 
        public Type TargetType { get; set; }
 
        public bool RunAsynchronously { get; set; } 

        public Activity Parent { get; set; } 

        // Sometimes we may know the result type even if it won't be used,
        // i.e. it comes from an InvokeMethod. We will want to generate
        // errors if it doesn't match the method's return value. 
        internal Type ResultType { get; set; }
 
        static bool HaveParameterArray(ParameterInfo[] parameters) 
        {
            if (parameters.Length > 0) 
            {
                ParameterInfo last = parameters[parameters.Length - 1];
                return last.GetCustomAttributes(typeof(ParamArrayAttribute), true).Length > 0;
            } 
            else
            { 
                return false; 
            }
        } 

        // The Arguments added by the activity are named according to the method resolved by the MethodResolver.
        public void RegisterParameters(IList arguments)
        { 
            bool useAsyncPattern = this.RunAsynchronously && this.beginMethod != null && this.endMethod != null;
 
            if (this.syncMethod != null || useAsyncPattern) 
            {
                ParameterInfo[] formalParameters; 
                int formalParamCount;
                string paramArrayBaseName = "";
                bool haveParameterArray = false;
 
                if (useAsyncPattern)
                { 
                    formalParameters = this.beginMethod.GetParameters(); 
                    formalParamCount = formalParameters.Length - 2;
                } 
                else
                {
                    formalParameters = this.syncMethod.GetParameters();
                    haveParameterArray = HaveParameterArray(formalParameters); 

                    if (haveParameterArray) 
                    { 
                        formalParamCount = formalParameters.Length - 1;
                        paramArrayBaseName = formalParameters[formalParamCount].Name; 
                    }
                    else
                    {
                        formalParamCount = formalParameters.Length; 
                    }
                } 
 
                for (int i = 0; i < formalParamCount; i++)
                { 
                    string name = formalParameters[i].Name;
                    //for some methods like int[,].Get(int,int), formal parameters have no names in reflection info
                    if (string.IsNullOrEmpty(name))
                    { 
                        name = "Parameter" + i;
                    } 
 
                    RuntimeArgument argument = new RuntimeArgument(name, Parameters[i].ArgumentType, Parameters[i].Direction, true);
                    Argument.Bind(Parameters[i], argument); 
                    arguments.Add(argument);

                    if (!useAsyncPattern && haveParameterArray)
                    { 
                        // Attempt to uniquify parameter names
                        if (name.StartsWith(paramArrayBaseName, false, null)) 
                        { 
                            int n;
                            if (int.TryParse(name.Substring(paramArrayBaseName.Length), NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out n)) 
                            {
                                paramArrayBaseName += "_";
                            }
                        } 
                    }
                } 
 
                if (!useAsyncPattern && haveParameterArray)
                { 
                    // RuntimeArgument bindings need names. In the case of params arrays, synthesize names based on the name of the formal params parameter
                    // plus a counter.
                    int paramArrayCount = Parameters.Count - formalParamCount;
 
                    for (int i = 0; i < paramArrayCount; i++)
                    { 
                        string name = paramArrayBaseName + i; 
                        int index = formalParamCount + i;
                        RuntimeArgument argument = new RuntimeArgument(name, Parameters[index].ArgumentType, Parameters[index].Direction, true); 
                        Argument.Bind(Parameters[index], argument);
                        arguments.Add(argument);
                    }
                } 
            }
            else 
            { 
                // We're still at design-time: make up "fake" arguments based on the parameters
                for (int i = 0; i < Parameters.Count; i++) 
                {
                    string name = "argument" + i;
                    RuntimeArgument argument = new RuntimeArgument(name, Parameters[i].ArgumentType, Parameters[i].Direction, true);
                    Argument.Bind(Parameters[i], argument); 
                    arguments.Add(argument);
                } 
            } 
        }
 
        public void Trace()
        {
            bool useAsyncPattern = this.RunAsynchronously && this.beginMethod != null && this.endMethod != null;
 
            if (useAsyncPattern)
            { 
                if (TD.InvokeMethodUseAsyncPatternIsEnabled()) 
                {
                    TD.InvokeMethodUseAsyncPattern(this.Parent.DisplayName, this.beginMethod.ToString(), this.endMethod.ToString()); 
                }
            }
            else
            { 
                if (this.RunAsynchronously)
                { 
                    if (TD.InvokeMethodDoesNotUseAsyncPatternIsEnabled()) 
                    {
                        TD.InvokeMethodDoesNotUseAsyncPattern(this.Parent.DisplayName); 
                    }
                }
            }
        } 

        // Set methodExecutor, returning an error string if there are any problems (ambiguous match, etc.). 
        public void DetermineMethodInfo(CodeActivityMetadata metadata, out MethodExecutor methodExecutor) 
        {
            bool returnEarly = false; 

            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))
                { 
                    this.endMethod = null;
                    metadata.AddValidationError(SR.ReturnTypeIncompatible(this.endMethod.ReturnType.Name, 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;
                } 
            } 

            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) 
                {
                    methodExecutor = new AsyncWaitCallbackMethodExecutor(result, this.Parent, this.TargetType, this.TargetObject, this.Parameters, this.Result);
                }
                else 
                {
                    methodExecutor = new SyncMethodExecutor(result, this.Parent, this.TargetType, this.TargetObject, this.Parameters, this.Result); 
                } 
            }
        } 

        // 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 [....] 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;
        } 

        // returns null on failure instead of throwing an exception (okay because it's an internal method) 
        static MethodInfo Instantiate(MethodInfo method, Type[] genericTypeArguments) 
        {
            if (method.ContainsGenericParameters && method.GetGenericArguments().Length == genericTypeArguments.Length) 
            {
                try
                {
                    // Must be a MethodInfo because we've already filtered out constructors 
                    return ((MethodInfo)method).MakeGenericMethod(genericTypeArguments);
                } 
                catch (ArgumentException) 
                {
                    // Constraint violations will throw this exception--don't add to candidates 
                    return null;
                }
            }
            else 
            {
                return null; 
            } 
        }
 

        // Store information about a particular asynchronous method call so we can update out/ref parameters, know
        // when/what to return, etc.
        class InvokeMethodInstanceData 
        {
            public object TargetObject { get; set; } 
            public object[] ActualParameters { get; set; } 
            public object ReturnValue { get; set; }
            public bool ExceptionWasThrown { get; set; } 
            public Exception Exception { get; set; }
        }

        class InheritanceAndParamArrayAwareBinder : Binder 
        {
            Type[] genericTypeArguments; 
 
            Type declaringType; // Methods declared directly on this type are preferred, followed by methods on its parents, etc.
 
            internal bool SelectMethodCalled; // If this binder is actually used in resolution, it gets to do things like instantiate methods.
                                               // Set this flag to false before calling Type.GetMethod. Check this flag after.

            Activity parentActivity; // Used for generating AmbiguousMatchException error message 

            public InheritanceAndParamArrayAwareBinder(Type declaringType, Type[] genericTypeArguments, Activity parentActivity) 
            { 
                this.declaringType = declaringType;
                this.genericTypeArguments = genericTypeArguments; 
                this.parentActivity = parentActivity;
            }

            public override FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo[] match, object value, CultureInfo culture) 
            {
                throw FxTrace.Exception.AsError(new NotImplementedException()); 
            } 

            public override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state) 
            {
                throw FxTrace.Exception.AsError(new NotImplementedException());
            }
 
            public override object ChangeType(object value, Type type, CultureInfo culture)
            { 
                throw FxTrace.Exception.AsError(new NotImplementedException()); 
            }
 
            public override void ReorderArgumentArray(ref object[] args, object state)
            {
                throw FxTrace.Exception.AsError(new NotImplementedException());
            } 

            public override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers) 
            { 
                MethodBase[] methodCandidates;
                this.SelectMethodCalled = true; 

                if (this.genericTypeArguments.Length > 0)
                {
                    // Accept only generic methods which can be successfully instantiated w/ these parameters 
                    Collection methods = new Collection();
                    foreach (MethodBase method in match) 
                    { 
                        // Must be a MethodInfo because we've already filtered out constructors
                        MethodInfo instantiatedMethod = Instantiate((MethodInfo)method, this.genericTypeArguments); 
                        if(instantiatedMethod != null)
                        {
                            methods.Add(instantiatedMethod);
                        } 
                    }
                    methodCandidates = methods.ToArray(); 
                } 
                else
                { 
                    // Accept only candidates which are already instantiated
                    methodCandidates = match.Where(m => m.ContainsGenericParameters == false).ToArray();
                }
 
                if (methodCandidates.Length == 0)
                { 
                    return null; 
                }
 
                // Methods declared on this.declaringType class get top priority as matches
                Type declaringType = this.declaringType;
                MethodBase result = null;
                do 
                {
                    MethodBase[] methodsDeclaredHere = methodCandidates.Where(mb => mb.DeclaringType == declaringType).ToArray(); 
                    if (methodsDeclaredHere.Length > 0) 
                    {
                        // Try to find a match 
                        result = FindMatch(methodsDeclaredHere, bindingAttr, types, modifiers);
                    }
                    declaringType = declaringType.BaseType;
                } 
                while (declaringType != null && result == null); // short-circuit as soon as we find a match
 
                return result; // returns null if no match found 
            }
 
            MethodBase FindMatch(MethodBase[] methodCandidates, BindingFlags bindingAttr, Type[] types, ParameterModifier[] modifiers)
            {
                // Try the default binder first. Never gives false positive, but will fail to detect methods w/ parameter array because
                // it will not expand the formal parameter list when checking against actual parameters. 
                MethodBase result = Type.DefaultBinder.SelectMethod(bindingAttr, methodCandidates, types, modifiers);
 
                // Could be false negative, check for parameter array and if so condense it back to an array before re-checking. 
                if (result == null)
                { 
                    foreach (MethodBase method in methodCandidates)
                    {
                        MethodInfo methodInfo = method as MethodInfo;
                        ParameterInfo[] formalParams = methodInfo.GetParameters(); 
                        if (MethodResolver.HaveParameterArray(formalParams)) // Check if the last parameter of method is marked w/ "params" attribute
                        { 
                            Type elementType = formalParams[formalParams.Length - 1].ParameterType.GetElementType(); 

                            bool allCompatible = true; 
                            // There could be more actual parameters than formal parameters, because the formal parameter is a params T'[] for some T'.
                            // So, check that each actual parameter starting at position [formalParams.Length - 1] is compatible with T'.
                            for (int i = formalParams.Length - 1; i < types.Length - 1; i++)
                            { 
                                if (!TypeHelper.AreTypesCompatible(types[i], elementType))
                                { 
                                    allCompatible = false; 
                                    break;
                                } 
                            }

                            if (!allCompatible)
                            { 
                                continue;
                            } 
 
                            // Condense the actual parameter back to an array.
                            Type[] typeArray = new Type[formalParams.Length]; 
                            for (int i = 0; i < typeArray.Length - 1; i++)
                            {
                                typeArray[i] = types[i];
                            } 
                            typeArray[typeArray.Length - 1] = elementType.MakeArrayType();
 
                            // Recheck the condensed array 
                            MethodBase newFound = Type.DefaultBinder.SelectMethod(bindingAttr, new MethodBase[] { methodInfo }, typeArray, modifiers);
                            if (result != null && newFound != null) 
                            {
                                string type = newFound.ReflectedType.Name;
                                string name = newFound.Name;
                                string bindingType = bindingAttr == staticBindingFlags ? staticString : instanceString; 
                                throw FxTrace.Exception.AsError(new AmbiguousMatchException(SR.DuplicateMethodFound(type, bindingType, name, this.parentActivity.DisplayName)));
                            } 
                            else 
                            {
                                result = newFound; 
                            }
                        }
                    }
                } 
                return result;
            } 
 
            public override PropertyInfo SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers)
            { 
                throw FxTrace.Exception.AsError(new NotImplementedException());
            }
        }
 
        // Executes method synchronously
        class SyncMethodExecutor : MethodExecutor 
        { 

            MethodInfo syncMethod; 
            public SyncMethodExecutor(MethodInfo syncMethod, Activity invokingActivity,
                Type targetType, InArgument targetObject, Collection parameters,
                RuntimeArgument returnObject)
                : base(invokingActivity, targetType, targetObject, parameters, returnObject) 
            {
                Fx.Assert(syncMethod != null, "Must provide syncMethod"); 
                this.syncMethod = syncMethod; 
            }
 
            public override bool MethodIsStatic { get { return this.syncMethod.IsStatic; } }

            protected override IAsyncResult BeginMakeMethodCall(AsyncCodeActivityContext context, object target, AsyncCallback callback, object state)
            { 
                object[] actualParameters = EvaluateAndPackParameters(context, this.syncMethod, false);
 
                object result = this.InvokeAndUnwrapExceptions(this.syncMethod, target, actualParameters); 

                SetOutArgumentAndReturnValue(context, result, actualParameters); 

                return new CompletedAsyncResult(callback, state);
            }
 
            protected override void EndMakeMethodCall(AsyncCodeActivityContext context, IAsyncResult result)
            { 
                CompletedAsyncResult.End(result); 
            }
        } 

        // Executes method using paired Begin/End async pattern methods
        class AsyncPatternMethodExecutor : MethodExecutor
        { 

            MethodInfo beginMethod; 
            MethodInfo endMethod; 
            public AsyncPatternMethodExecutor(MethodInfo beginMethod, MethodInfo endMethod,
                Activity invokingActivity, Type targetType, InArgument targetObject, 
                Collection parameters, RuntimeArgument returnObject)
                : base(invokingActivity, targetType, targetObject, parameters, returnObject)
            {
                Fx.Assert(beginMethod != null && endMethod != null, "Must provide beginMethod and endMethod"); 
                this.beginMethod = beginMethod;
                this.endMethod = endMethod; 
            } 

            public override bool MethodIsStatic { get { return this.beginMethod.IsStatic; } } 

            protected override IAsyncResult BeginMakeMethodCall(AsyncCodeActivityContext context, object target, AsyncCallback callback, object state)
            {
                InvokeMethodInstanceData instance = new InvokeMethodInstanceData 
                {
                    TargetObject = target, 
                    ActualParameters = EvaluateAndPackParameters(context, this.beginMethod, true), 
                };
 
                int count = instance.ActualParameters.Length;

                instance.ActualParameters[count - 2] = callback;
                instance.ActualParameters[count - 1] = state; 
                context.UserState = instance;
 
                return (IAsyncResult)this.InvokeAndUnwrapExceptions(this.beginMethod, target, instance.ActualParameters); 
            }
 
            protected override void EndMakeMethodCall(AsyncCodeActivityContext context, IAsyncResult result)
            {
                InvokeMethodInstanceData instance = (InvokeMethodInstanceData)context.UserState;
                instance.ReturnValue = InvokeAndUnwrapExceptions(this.endMethod, instance.TargetObject, new object[] { result }); 
                this.SetOutArgumentAndReturnValue(context, instance.ReturnValue, instance.ActualParameters);
            } 
        } 

        // Executes method asynchronously on WaitCallback thread. 
        class AsyncWaitCallbackMethodExecutor : MethodExecutor
        {
            MethodInfo asyncMethod;
            public AsyncWaitCallbackMethodExecutor(MethodInfo asyncMethod, Activity invokingActivity, 
                Type targetType, InArgument targetObject, Collection parameters,
                RuntimeArgument returnObject) 
                : base(invokingActivity, targetType, targetObject, parameters, returnObject) 
            {
                Fx.Assert(asyncMethod != null, "Must provide asyncMethod"); 
                this.asyncMethod = asyncMethod;
            }

            public override bool MethodIsStatic { get { return this.asyncMethod.IsStatic; } } 

            protected override IAsyncResult BeginMakeMethodCall(AsyncCodeActivityContext context, object target, AsyncCallback callback, object state) 
            { 
                InvokeMethodInstanceData instance = new InvokeMethodInstanceData
                { 
                    TargetObject = target,
                    ActualParameters = EvaluateAndPackParameters(context, this.asyncMethod, false),
                };
                return new ExecuteAsyncResult(instance, this, callback, state); 
            }
 
            protected override void EndMakeMethodCall(AsyncCodeActivityContext context, IAsyncResult result) 
            {
                InvokeMethodInstanceData instance = ExecuteAsyncResult.End(result); 
                if (instance.ExceptionWasThrown)
                {
                    throw FxTrace.Exception.AsError(instance.Exception);
                } 
                else
                { 
                    this.SetOutArgumentAndReturnValue(context, instance.ReturnValue, instance.ActualParameters); 
                }
            } 

            class ExecuteAsyncResult : AsyncResult
            {
                static Action asyncExecute = new Action(AsyncExecute); 
                InvokeMethodInstanceData instance;
                AsyncWaitCallbackMethodExecutor executor; 
 
                public ExecuteAsyncResult(InvokeMethodInstanceData instance, AsyncWaitCallbackMethodExecutor executor, AsyncCallback callback, object state)
                    : base(callback, state) 
                {
                    this.instance = instance;
                    this.executor = executor;
                    ActionItem.Schedule(asyncExecute, this); 
                }
 
                public static InvokeMethodInstanceData End(IAsyncResult result) 
                {
                    ExecuteAsyncResult thisPtr = AsyncResult.End(result); 
                    return thisPtr.instance;
                }

                static void AsyncExecute(object state) 
                {
                    ExecuteAsyncResult thisPtr = (ExecuteAsyncResult)state; 
                    thisPtr.AsyncExecuteCore(); 
                }
 
                void AsyncExecuteCore()
                {
                    try
                    { 
                        this.instance.ReturnValue = this.executor.InvokeAndUnwrapExceptions(this.executor.asyncMethod, this.instance.TargetObject, this.instance.ActualParameters);
                    } 
                    catch (Exception e) 
                    {
                        if(Fx.IsFatal(e)) 
                        {
                            throw;
                        }
                        this.instance.Exception = e; 
                        this.instance.ExceptionWasThrown = true;
                    } 
                    base.Complete(false); 
                }
            } 
        }
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

                        

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