Ejemplo n.º 1
0
        /// <summary>
        /// Builds <see cref="HandlerDescriptor"/> for <paramref name="handler"/> and its <paramref name="argumentType"/> (wrapper or unwrapper).
        /// </summary>
        /// <param name="handler">The handler to build descriptor for.</param>
        /// <param name="argumentType">The argument type (possibly wrapped in envelope or context).</param>
        /// <returns>The instance of the handler descriptor.</returns>
        public HandlerDescriptor Get(object handler, Type argumentType)
        {
            Ensure.NotNull(handler, "handler");
            Type handlerType = handler.GetType();

            string handlerIdentifier = FindIdentifier(handlerType);

            MethodInfo method = handlerType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                                .FirstOrDefault(m => m.Name.EndsWith(methodName) && m.GetParameters()[0].ParameterType == argumentType);

            Func <object, object, Action <Exception>, Task> handlerAction = (h, p, additionalExceptionDecorator) =>
            {
                try
                {
                    Task result = (Task)method.Invoke(h, new object[] { p });
                    result = result.ContinueWith(task =>
                    {
                        if (task.IsFaulted)
                        {
                            innerExceptionHandlers.Handle(task.Exception.InnerException);
                            return(Async.CompletedTask);
                        }

                        return(task);
                    });
                    return(result);
                }
                catch (TargetInvocationException e)
                {
                    if (additionalExceptionDecorator != null)
                    {
                        additionalExceptionDecorator(e.InnerException);
                    }

                    innerExceptionHandlers.Handle(e.InnerException);
                    return(Async.CompletedTask);
                }
                catch (Exception e)
                {
                    if (additionalExceptionDecorator != null)
                    {
                        additionalExceptionDecorator(e);
                    }

                    outerExceptionHandlers.Handle(e);
                    return(Async.CompletedTask);
                }
            };

            ArgumentDescriptor argument = Get(argumentType);

            return(new HandlerDescriptor(
                       handlerIdentifier,
                       handler,
                       argument.ArgumentType,
                       handlerAction,
                       argument.IsPlain,
                       argument.IsEnvelope,
                       argument.IsContext
                       ));
        }