Пример #1
0
        public Task MapAsync(Func <IContainer> container, Type type, MethodInfo method, Routing.Route route)
        {
            container.ThrowIfNull("container");
            type.ThrowIfNull("type");
            method.ThrowIfNull("method");
            route.ThrowIfNull("route");

            route.RespondWithNoContent();

            return(Task.Factory.Empty());
        }
Пример #2
0
        public Task MapAsync(Func <IContainer> container, Type type, MethodInfo method, Routing.Route route)
        {
            container.ThrowIfNull("container");
            type.ThrowIfNull("type");
            method.ThrowIfNull("method");
            route.ThrowIfNull("route");

            bool methodReturnTypeImplementsIResponse = method.ReturnType.ImplementsInterface <IResponse>();
            bool methodReturnTypeIsTaskT             = method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task <>);
            bool methodReturnTypeIsVoid = method.ReturnType == typeof(void);

            if (methodReturnTypeImplementsIResponse)
            {
                ParameterInfo[]     parameterInfos = method.GetParameters();
                ParameterExpression instanceParameterExpression   = Expression.Parameter(typeof(object), "instance");
                ParameterExpression parametersParameterExpression = Expression.Parameter(typeof(object[]), "parameters");
                UnaryExpression     unaryExpression =
                    Expression.Convert(
                        Expression.Call(
                            Expression.Convert(instanceParameterExpression, type),
                            method,
                            parameterInfos.Select((arg, index) => Expression.Convert(
                                                      Expression.ArrayIndex(parametersParameterExpression, Expression.Constant(index)),
                                                      arg.ParameterType))),
                        typeof(IResponse));
                Func <object, object[], IResponse> @delegate = Expression.Lambda <Func <object, object[], IResponse> >(unaryExpression, instanceParameterExpression, parametersParameterExpression).Compile();

                route.RespondWith(
                    async context =>
                {
                    object instance;

                    try
                    {
                        instance = container().GetInstance(type);
                    }
                    catch (Exception exception)
                    {
                        throw new ApplicationException(String.Format("Unable to resolve instance of type {0}.", type.FullName), exception);
                    }
                    if (instance == null)
                    {
                        throw new ApplicationException(String.Format("Unable to resolve instance of type {0}.", type.FullName));
                    }

                    var parameterValueRetriever = new ParameterValueRetriever(_parameterMappers);
                    object[] parameterValues    = (await parameterValueRetriever.GetParameterValuesAsync(context, type, method)).ToArray();

                    return(@delegate(instance, parameterValues));
                },
                    method.ReturnType);
            }
            else if (methodReturnTypeIsTaskT)
            {
                ParameterInfo[]     parameterInfos = method.GetParameters();
                ParameterExpression instanceParameterExpression   = Expression.Parameter(typeof(object), "instance");
                ParameterExpression parametersParameterExpression = Expression.Parameter(typeof(object[]), "parameters");
                Type       methodGenericArgumentType = method.ReturnType.GetGenericArguments()[0];
                MethodInfo upcastMethodInfo          = typeof(TaskExtensions)
                                                       .GetMethod("Upcast", BindingFlags.Static | BindingFlags.Public)
                                                       .MakeGenericMethod(methodGenericArgumentType, typeof(IResponse));
                UnaryExpression unaryExpression =
                    Expression.Convert(
                        Expression.Call(
                            upcastMethodInfo,
                            Expression.Call(
                                Expression.Convert(instanceParameterExpression, type),
                                method,
                                parameterInfos.Select((arg, index) => Expression.Convert(
                                                          Expression.ArrayIndex(parametersParameterExpression, Expression.Constant(index)),
                                                          arg.ParameterType)))),
                        upcastMethodInfo.ReturnType);
                Func <object, object[], Task <IResponse> > @delegate = Expression.Lambda <Func <object, object[], Task <IResponse> > >(unaryExpression, instanceParameterExpression, parametersParameterExpression).Compile();

                route.RespondWith(
                    async context =>
                {
                    object instance;

                    try
                    {
                        instance = container().GetInstance(type);
                    }
                    catch (Exception exception)
                    {
                        throw new ApplicationException(String.Format("Unable to resolve instance of type {0}.", type.FullName), exception);
                    }
                    if (instance == null)
                    {
                        throw new ApplicationException(String.Format("Unable to resolve instance of type {0}.", type.FullName));
                    }

                    var parameterValueRetriever = new ParameterValueRetriever(_parameterMappers);
                    object[] parameterValues    = (await parameterValueRetriever.GetParameterValuesAsync(context, type, method)).ToArray();

                    return(await @delegate(instance, parameterValues));
                },
                    methodGenericArgumentType);
            }
            else if (methodReturnTypeIsVoid)
            {
                ParameterInfo[]      parameterInfos = method.GetParameters();
                ParameterExpression  instanceParameterExpression   = Expression.Parameter(typeof(object), "instance");
                ParameterExpression  parametersParameterExpression = Expression.Parameter(typeof(object[]), "parameters");
                MethodCallExpression methodCallExpression          =
                    Expression.Call(
                        Expression.Convert(instanceParameterExpression, type),
                        method,
                        parameterInfos.Select((arg, index) => Expression.Convert(
                                                  Expression.ArrayIndex(parametersParameterExpression, Expression.Constant(index)),
                                                  arg.ParameterType)));
                Action <object, object[]> @delegate = Expression.Lambda <Action <object, object[]> >(methodCallExpression, instanceParameterExpression, parametersParameterExpression).Compile();

                route.RespondWithNoContent(
                    async context =>
                {
                    object instance;

                    try
                    {
                        instance = container().GetInstance(type);
                    }
                    catch (Exception exception)
                    {
                        throw new ApplicationException(String.Format("Unable to resolve instance of type {0}.", type.FullName), exception);
                    }
                    if (instance == null)
                    {
                        throw new ApplicationException(String.Format("Unable to resolve instance of type {0}.", type.FullName));
                    }

                    var parameterValueRetriever = new ParameterValueRetriever(_parameterMappers);
                    object[] parameterValues    = (await parameterValueRetriever.GetParameterValuesAsync(context, type, method)).ToArray();

                    @delegate(instance, parameterValues);
                });
            }
            else
            {
                throw new ApplicationException(String.Format("The return type of {0}.{1} must implement {2} or be a {3} whose generic type argument implements {2}.", type.FullName, method.Name, typeof(IResponse).Name, typeof(Task <>)));
            }

            return(Task.Factory.Empty());
        }