예제 #1
0
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            //if the polling interval is zero (or less) run this request synchronously
            if (this._pollingIntervalMilliseconds <= 0)
            {
                return(this.ServiceBusClient.TryInvokeMember(binder, args, out result));
            }

            result = null;
            var info   = binder.CallInfo;
            var method = binder.Name;

            // accepting named args only... SKEET!
            if (info.ArgumentNames.Count != args.Length)
            {
                throw new InvalidOperationException("Please use named arguments.");
            }

            //stuff parameters into case insensitive dictionary
            var parameters = new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase);

            for (int i = 0; i < args.Length; i++)
            {
                parameters.Add(info.ArgumentNames[i], args[i]);
            }

            var token = ServiceBusClient.AsyncProcess().ExecuteAsyncProcess(method, parameters);



            //the only way to determine if generic type parameters have been used is reflection
            var  csharpBinder = binder.GetType().GetInterface("Microsoft.CSharp.RuntimeBinder.ICSharpInvokeOrInvokeMemberBinder");
            var  typeArgs     = csharpBinder.GetProperty("TypeArguments").GetValue(binder, null) as IList <Type>;
            Type returnType   = typeArgs.FirstOrDefault();

            //if it exists, the first generic type parameter is our return type (e.g. myObject.MyMethod<int>(Id: 123); --> returnType would be typeof(int))
            if (returnType != null)
            {
                MethodInfo genericMethodInfo = _asyncDynamicMethodInfo.MakeGenericMethod(returnType);
                try
                {
                    var sw = Stopwatch.StartNew();
                    while (sw.ElapsedMilliseconds <= PollingTimeout.Value.TotalMilliseconds)
                    {
                        //async get result
                        var asyncResult = genericMethodInfo.Invoke(ServiceBusClient.AsyncProcess(), new object[] { (string)token });

                        //examine result
                        PropertyInfo statusPropertyInfo = asyncResult.GetType().GetProperty("Status");
                        Status       asyncStatus        = (Status)statusPropertyInfo.GetValue(asyncResult);
                        if (asyncStatus == Status.Done)
                        {
                            PropertyInfo resultPropertyInfo = asyncResult.GetType().GetProperty("Result");
                            result = resultPropertyInfo.GetValue(asyncResult);
                            return(true);
                        }
                        else if (asyncStatus == Status.NotFound)
                        {
                            //todo create a custom exception
                            throw new AsyncNotFoundException();
                        }

                        //wait our polling interval
                        Thread.Sleep(_pollingIntervalMilliseconds);
                    }//end while (not timed out)

                    //if we've made it here... timed out
                    throw new AsyncTimeoutException();
                }
                catch (TargetInvocationException tiex)
                {
                    throw tiex.InnerException;
                }
            }
            else
            {
                var sw = Stopwatch.StartNew();
                while (sw.ElapsedMilliseconds <= PollingTimeout.Value.TotalMilliseconds)
                {
                    //async get result
                    AsyncResult asyncResult = ServiceBusClient.AsyncProcess().GetAsyncResult((string)token) as AsyncResult;

                    //examine result
                    if (asyncResult.Status == Status.Done)
                    {
                        result = asyncResult.Result;
                        return(true);
                    }
                    else if (asyncResult.Status == Status.NotFound)
                    {
                        //todo create a custom exception
                        throw new AsyncNotFoundException();
                    }

                    //wait our polling interval
                    Thread.Sleep(_pollingIntervalMilliseconds);
                }//end while (not timed out)

                //if we've made it here... timed out
                throw new AsyncTimeoutException();
            }
        }