public static void UseStubomatic(this HttpConfiguration configuration, StubomaticOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
            if (options.ResolveFrom == ResolveFrom.ControllerType && options.ControllerTypeResolver == null)
            {
                throw new ArgumentException("options.ControllerTypeResolver cannot be null");
            }
            if (options.ResolveFrom == ResolveFrom.ResponseType && options.ResponseTypeResolver == null)
            {
                throw new ArgumentException("options.ResponseTypeResolver cannot be null");
            }

            configuration.Services.Replace(typeof(IAssembliesResolver), new StubomaticAssembliesResolver(configuration.Services.GetAssembliesResolver(), options));
            configuration.Services.Replace(typeof(IHttpControllerTypeResolver), new StubomaticHttpControllerTypeResolver(configuration.Services.GetHttpControllerTypeResolver()));
        }
Beispiel #2
0
        private static Type GetStubProxyType(this ModuleBuilder moduleBuilder, Type controllerType, StubomaticOptions options)
        {
            Type            stubType        = null;
            ConstructorInfo stubConstructor = null;

            if (options.ResolveFrom == ResolveFrom.ControllerType)
            {
                stubType        = options.ControllerTypeResolver.GetStubType(controllerType);
                stubConstructor = (stubType != null) ? stubType.GetConstructor(Type.EmptyTypes) : null;
                if (stubConstructor == null) // no stub class with default constructor
                {
                    if (options.MissingStubHandling == MissingStubHandling.NotFound)
                    {
                        return(null);
                    }
                    if (options.MissingStubHandling == MissingStubHandling.Exception)
                    {
                        throw new StubNotFoundException(controllerType.FullName);
                    }
                }
            }

            var stubTypeName = (stubConstructor != null) ? stubType.Name : controllerType.Name;
            var typeName     = string.Format("{0}{1:N}Controller", stubTypeName, Guid.NewGuid());
            var typeBuilder  = moduleBuilder.DefineType(typeName, TypeAttributes.Public | TypeAttributes.Class, typeof(ApiController));

            FieldBuilder stubFieldBuilder = (stubConstructor != null) ? typeBuilder.DefineStubField(stubType) : null; // generate stub field

            typeBuilder.DefineConstructor(stubFieldBuilder, stubConstructor);                                         // generate default constructor to initialise stub field

            foreach (var controllerMethod in controllerType.GetMethodsToProxy())                                      // generate proxy methods
            {
                if (options.ResolveFrom == ResolveFrom.ControllerType)
                {
                    typeBuilder.DefineControllerTypeProxyMethod(controllerMethod, stubFieldBuilder, options);
                }
                if (options.ResolveFrom == ResolveFrom.ResponseType)
                {
                    typeBuilder.DefineResponseTypeProxyMethod(controllerMethod, options);
                }
            }

            return(typeBuilder.CreateType());
        }
Beispiel #3
0
        private static CustomAttributeBuilder ToAttributeBuilder(this CustomAttributeData data, StubomaticOptions options)
        {
            if (data == null || data.NamedArguments == null)
            {
                return(null);
            }

            var constructorArguments = new List <object>();

            var routeAttributeTemplateParameterIndex = -1;
            var routeAttributeType = typeof(RouteAttribute);

            if (data.AttributeType.IsSubclassOf(routeAttributeType) || data.AttributeType == routeAttributeType)
            {
                var templateParameter = data.Constructor.GetParameters().FirstOrDefault(p => p.Name == "template");
                if (templateParameter != null)
                {
                    routeAttributeTemplateParameterIndex = templateParameter.Position;
                }
            }

            var index = 0;

            foreach (var ctorArg in data.ConstructorArguments)
            {
                var argValue = ctorArg.Value;
                if (routeAttributeTemplateParameterIndex == index)
                {
                    argValue = options.RoutePrefix + (string)argValue;
                }
                constructorArguments.Add(argValue);
                index += 1;
            }

            var propertyArguments      = new List <PropertyInfo>();
            var propertyArgumentValues = new List <object>();
            var fieldArguments         = new List <FieldInfo>();
            var fieldArgumentValues    = new List <object>();

            foreach (var namedArg in data.NamedArguments)
            {
                var fi = namedArg.MemberInfo as FieldInfo;
                var pi = namedArg.MemberInfo as PropertyInfo;

                if (fi != null)
                {
                    fieldArguments.Add(fi);
                    fieldArgumentValues.Add(namedArg.TypedValue.Value);
                }
                else if (pi != null)
                {
                    propertyArguments.Add(pi);
                    propertyArgumentValues.Add(namedArg.TypedValue.Value);
                }
            }
            return(new CustomAttributeBuilder(
                       data.Constructor,
                       constructorArguments.ToArray(),
                       propertyArguments.ToArray(),
                       propertyArgumentValues.ToArray(),
                       fieldArguments.ToArray(),
                       fieldArgumentValues.ToArray()));
        }
Beispiel #4
0
        private static MethodBuilder DefineProxyMethod(this TypeBuilder typeBuilder, MethodInfo controllerMethod, StubomaticOptions options, Type returnType, Action <ILGenerator> stubber)
        {
            var methodBuilder = typeBuilder.DefineMethod(controllerMethod.Name, controllerMethod.Attributes, controllerMethod.CallingConvention, typeof(IHttpActionResult), controllerMethod.GetParameterTypes());

            foreach (var parameter in controllerMethod.GetParameters())
            {
                methodBuilder.DefineParameter(parameter.Position + 1, parameter.Attributes, parameter.Name); // wtf is Position being inconsistently 0 or 1 based!
            }
            foreach (var attribute in controllerMethod.GetCustomAttributesData())
            {
                var attributeBuilder = attribute.ToAttributeBuilder(options);
                if (attributeBuilder == null)
                {
                    continue;
                }
                methodBuilder.SetCustomAttribute(attributeBuilder);                                     // copy custom attribute
            }

            var okMethod = ApiControllerOkMethod.Value.MakeGenericMethod(returnType);

            var ilGenerator = methodBuilder.GetILGenerator();

            ilGenerator.Emit(OpCodes.Ldarg_0);                                                          // push this on to stack
            if (stubber != null)
            {
                stubber(ilGenerator);
            }
            else
            {
                ilGenerator.Emit(OpCodes.Ldstr, options.MissingStubHandlingMessage);
            }
            ilGenerator.Emit(OpCodes.Call, okMethod);                                                   // call Ok method
            ilGenerator.Emit(OpCodes.Ret);                                                              // finish

            return(methodBuilder);
        }
Beispiel #5
0
        private static MethodBuilder DefineResponseTypeProxyMethod(this TypeBuilder typeBuilder, MethodInfo controllerMethod, StubomaticOptions options)
        {
            var responseTypeAttribute = controllerMethod.GetCustomAttribute <ResponseTypeAttribute>();
            var responseType          = responseTypeAttribute != null ? responseTypeAttribute.ResponseType : null;
            var stubber    = options.ResponseTypeResolver.GetILGenerator(responseType);
            var stubExists = stubber != null;

            if (!stubExists)
            {
                if (options.MissingStubHandling == MissingStubHandling.NotFound)
                {
                    return(null);
                }
                if (options.MissingStubHandling == MissingStubHandling.Exception)
                {
                    throw new StubNotFoundException((controllerMethod.DeclaringType != null) ? controllerMethod.DeclaringType.FullName + "." + controllerMethod.Name : controllerMethod.Name);                                                               // no corresponding response type stub
                }
            }

            var returnType = (stubExists) ? responseType : typeof(string);

            return(typeBuilder.DefineProxyMethod(controllerMethod, options, returnType, stubber));
        }
Beispiel #6
0
        private static MethodBuilder DefineControllerTypeProxyMethod(this TypeBuilder typeBuilder, MethodInfo controllerMethod, FieldBuilder stubFieldBuilder, StubomaticOptions options)
        {
            var parameterTypes = controllerMethod.GetParameterTypes();
            var stubMethod     = (stubFieldBuilder != null) ? stubFieldBuilder.FieldType.GetMethod(controllerMethod.Name, parameterTypes) : null;
            var stubExists     = stubFieldBuilder != null && stubMethod != null;

            if (!stubExists)
            {
                if (options.MissingStubHandling == MissingStubHandling.NotFound)
                {
                    return(null);
                }
                if (options.MissingStubHandling == MissingStubHandling.Exception)
                {
                    throw new StubNotFoundException((controllerMethod.DeclaringType != null) ? controllerMethod.DeclaringType.FullName + "." + controllerMethod.Name : controllerMethod.Name);                                                               // no corresponding stub method
                }
            }

            var returnType = (stubExists) ? stubMethod.ReturnType : typeof(string);
            var stubber    = (stubExists) ?
                             new Action <ILGenerator>((ilGenerator) =>
            {
                ilGenerator.Emit(OpCodes.Ldarg_0);                                                          // push this on to stack
                ilGenerator.Emit(OpCodes.Ldfld, stubFieldBuilder);                                          // push stub field on to stack
                for (int i = 1; i <= parameterTypes.Length; i++)
                {
                    ilGenerator.Emit(OpCodes.Ldarg, i);                                                     // push parameters onto stack
                }
                ilGenerator.Emit(OpCodes.Call, stubMethod);                                                 // call stub method
            }) : null;

            return(typeBuilder.DefineProxyMethod(controllerMethod, options, returnType, stubber));
        }
Beispiel #7
0
        internal static Assembly CreateStubAssembly(this IEnumerable <Type> controllerTypes, StubomaticOptions options)
        {
            var assemblyBuilder = AppDomain.CurrentDomain.DefineStubAssembly();
            var moduleBuilder   = assemblyBuilder.DefineStubModule();

            foreach (var controllerType in controllerTypes)
            {
                moduleBuilder.GetStubProxyType(controllerType, options);
            }

            //assemblyBuilder.Save("stubs.assembly.dll");

            return(assemblyBuilder);
        }
Beispiel #8
0
 public StubomaticAssembliesResolver(IAssembliesResolver resolver, StubomaticOptions options)
 {
     _resolver     = resolver;
     _stubAssembly = new Lazy <Assembly>(() => _resolver.GetAssemblies().SelectMany(a => a.GetTypes().Where(i => typeof(ApiController).IsAssignableFrom(i))).CreateStubAssembly(options));
 }