예제 #1
0
        private static Action <IOwinContext, object> Setter(MemberInfo member)
        {
            var attr = member.GetAttribute <BindingAttribute>();
            var name = string.IsNullOrEmpty(attr.Name) ? member.Name : attr.Name;
            var type = member is PropertyInfo ? ((PropertyInfo)member).PropertyType : ((FieldInfo)member).FieldType;

            var getter = Getter(attr.Target, name, type);
            var setter = DynamicMethods.CompileSetter(member.DeclaringType, member);

            return((ctx, instance) =>
            {
                var value = getter(ctx);
                if (value == null)
                {
                    return;
                }
                setter(instance, value);
            });
        }
예제 #2
0
        internal static Func <IOwinContext, object> CompileInitializer(Type type)
        {
            var ctors = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance);

            if (ctors.Length > 1)
            {
                throw new InvalidOperationException(string.Format(
                                                        "Dependency injector cannot create instance for type {0} since it has multiple constructors.",
                                                        type.FullName));
            }

            var ctor       = ctors[0];
            var create     = DynamicMethods.CompileConstructor(ctor);
            var paramTypes = (from p in ctor.GetParameters() select p.ParameterType).ToArray();

            var props = (from p in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                         where p.GetIndexParameters().Length == 0
                         let setter = DynamicMethods.CompileSetter(type, p)
                                      where setter != null
                                      select new
            {
                Type = p.PropertyType,
                Setter = setter
            }).ToArray();

            return(ctx =>
            {
                var serviceProvider = GetServiceProvider(ctx);
                Func <Type, object> resolveDep = t =>
                {
                    if (t == typeof(IServiceProvider))
                    {
                        return serviceProvider;
                    }
                    if (t == typeof(IOwinContext))
                    {
                        return ctx;
                    }
                    if (t == typeof(IOwinRequest))
                    {
                        return ctx.Request;
                    }
                    if (t == typeof(IOwinResponse))
                    {
                        return ctx.Response;
                    }
                    return serviceProvider.GetService(t);
                };

                var args = (from t in paramTypes select resolveDep(t)).ToArray();
                var instance = create(args);

                foreach (var prop in props)
                {
                    var value = resolveDep(prop.Type);
                    prop.Setter(instance, value);
                }

                return instance;
            });
        }
예제 #3
0
        /// <summary>
        /// Registers methods annotated with <see cref="RouteAttribute"/> into routing pipeline.
        /// </summary>
        /// <typeparam name="T">Type to reflect.</typeparam>
        /// <param name="mapRouteBuilder">The fluent API to register http method handlers.</param>
        /// <param name="getInstance">Function to get instance of T.</param>
        /// <returns></returns>
        public static MapRouteBuilder UseApi <T>(this MapRouteBuilder mapRouteBuilder, Func <IOwinContext, T> getInstance)
        {
            if (getInstance == null)
            {
                throw new ArgumentNullException("getInstance");
            }

            var type       = typeof(T);
            var prefixAttr = type.GetAttribute <RoutePrefixAttribute>();
            var prefix     = prefixAttr != null ? prefixAttr.Prefix : string.Empty;

            var serializerSettings = type.GetProperties(BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.Public)
                                     .Where(p => p.HasAttribute <ResponseSerializerSettingsAttribute>() && p.PropertyType == typeof(JsonSerializerSettings))
                                     .Select(p => p.GetValue(null) as JsonSerializerSettings)
                                     .FirstOrDefault();

            var errorHandler = type.GetMethods(BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.Public)
                               .Where(m => m.HasAttribute <ErrorHandlerAttribute>())
                               .Select(m => DynamicMethods.CompileMethod(type, m))
                               .FirstOrDefault();

            const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;

            var actions = (from m in type.GetMethods(bindingFlags)
                           let route = m.GetAttribute <RouteAttribute>()
                                       where route != null
                                       select new { Method = m, Route = route }).ToList();

            actions.ForEach(a =>
            {
                var invoke     = DynamicMethods.CompileMethod(type, a.Method);
                var mapper     = ParameterMapper.Build(a.Method);
                var returnType = a.Method.ReturnType;

                var verb    = GetHttpMethod(a.Method);
                var pattern = AddPrefix(prefix, a.Route.Template);

                mapRouteBuilder.Register(pattern, verb, async ctx =>
                {
                    Exception error;
                    var args = MapParameters(ctx, mapper, out error);
                    if (error != null)
                    {
                        if (null != errorHandler)
                        {
                            var errorResponse = errorHandler(null, new object[] { ctx, error });
                            if (null != errorResponse)
                            {
                                await ctx.WriteJson(errorResponse);
                            }
                        }
                        else
                        {
                            ctx.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                            await ctx.WriteJson(new { error = error.Message });
                        }
                        return;
                    }

                    var instance = a.Method.IsStatic ? (object)null : getInstance(ctx);
                    var result   = invoke(instance, args);

                    var task = result as Task;
                    if (null != task)
                    {
                        result = await HandleAsyncResult(task, returnType);
                    }

                    if (result != null)
                    {
                        await ctx.WriteJson(result, serializerSettings);
                    }
                });
            });

            return(mapRouteBuilder);
        }