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); }); }
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; }); }
/// <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); }