Exemplo n.º 1
0
        /// <summary>
        /// Registers all controllers in the specified assembly which are marked with the MessageController attribute.
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="assembly">The assembly to scan for controllers.</param>
        public static ITapetiConfigBuilder RegisterAllControllers(this ITapetiConfigBuilder builder, Assembly assembly)
        {
            foreach (var type in assembly.GetTypes().Where(t => t.IsDefined(typeof(MessageControllerAttribute))))
            {
                RegisterController(builder, type);
            }

            return(builder);
        }
Exemplo n.º 2
0
 /// <summary>
 /// Enables the Flow SQL repository.
 /// </summary>
 /// <param name="config"></param>
 /// <param name="connectionString"></param>
 /// <param name="tableName"></param>
 public static ITapetiConfigBuilder WithFlowSqlRepository(this ITapetiConfigBuilder config, string connectionString, string tableName = "Flow")
 {
     config.Use(new FlowSqlRepositoryExtension(connectionString, tableName));
     return(config);
 }
Exemplo n.º 3
0
 /// <summary>
 /// Enables the DataAnnotations validation middleware.
 /// </summary>
 /// <param name="config"></param>
 public static ITapetiConfigBuilder WithDataAnnotations(this ITapetiConfigBuilder config)
 {
     config.Use(new DataAnnotationsExtension());
     return(config);
 }
Exemplo n.º 4
0
        /// <summary>
        /// Registers all public methods in the specified controller class as message handlers.
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="controller">The controller class to register. The class and/or methods must be annotated with either the DurableQueue or DynamicQueue attribute.</param>
        public static ITapetiConfigBuilder RegisterController(this ITapetiConfigBuilder builder, Type controller)
        {
            var builderAccess = (ITapetiConfigBuilderAccess)builder;

            if (!controller.IsClass)
            {
                throw new ArgumentException($"Controller {controller.Name} must be a class");
            }

            var controllerQueueInfo = GetQueueInfo(controller);

            (builderAccess.DependencyResolver as IDependencyContainer)?.RegisterController(controller);

            var controllerIsObsolete = controller.GetCustomAttribute <ObsoleteAttribute>() != null;


            foreach (var method in controller.GetMembers(BindingFlags.Public | BindingFlags.Instance)
                     .Where(m => m.MemberType == MemberTypes.Method && m.DeclaringType != typeof(object) && (m as MethodInfo)?.IsSpecialName == false)
                     .Select(m => (MethodInfo)m))
            {
                var methodIsObsolete = controllerIsObsolete || method.GetCustomAttribute <ObsoleteAttribute>() != null;

                var context = new ControllerBindingContext(method.GetParameters(), method.ReturnParameter)
                {
                    Controller = controller,
                    Method     = method
                };


                if (method.GetCustomAttribute <ResponseHandlerAttribute>() != null)
                {
                    context.SetBindingTargetMode(BindingTargetMode.Direct);
                }


                var allowBinding = false;
                builderAccess.ApplyBindingMiddleware(context, () => { allowBinding = true; });

                if (!allowBinding)
                {
                    continue;
                }


                if (context.MessageClass == null)
                {
                    throw new TopologyConfigurationException($"Method {method.Name} in controller {controller.Name} does not resolve to a message class");
                }


                var invalidBindings = context.Parameters.Where(p => !p.HasBinding).ToList();
                if (invalidBindings.Count > 0)
                {
                    var parameterNames = string.Join(", ", invalidBindings.Select(p => p.Info.Name));
                    throw new TopologyConfigurationException($"Method {method.Name} in controller {method.DeclaringType?.Name} has unknown parameters: {parameterNames}");
                }

                var methodQueueInfo = GetQueueInfo(method) ?? controllerQueueInfo;
                if (methodQueueInfo == null || !methodQueueInfo.IsValid)
                {
                    throw new TopologyConfigurationException(
                              $"Method {method.Name} or controller {controller.Name} requires a queue attribute");
                }

                builder.RegisterBinding(new ControllerMethodBinding(builderAccess.DependencyResolver, new ControllerMethodBinding.BindingInfo
                {
                    ControllerType     = controller,
                    Method             = method,
                    QueueInfo          = methodQueueInfo,
                    MessageClass       = context.MessageClass,
                    BindingTargetMode  = context.BindingTargetMode,
                    IsObsolete         = methodIsObsolete,
                    ParameterFactories = context.GetParameterHandlers(),
                    ResultHandler      = context.GetResultHandler(),

                    FilterMiddleware  = context.Middleware.Where(m => m is IControllerFilterMiddleware).Cast <IControllerFilterMiddleware>().ToList(),
                    MessageMiddleware = context.Middleware.Where(m => m is IControllerMessageMiddleware).Cast <IControllerMessageMiddleware>().ToList(),
                    CleanupMiddleware = context.Middleware.Where(m => m is IControllerCleanupMiddleware).Cast <IControllerCleanupMiddleware>().ToList()
                }));
            }

            return(builder);
        }
Exemplo n.º 5
0
 /// <summary>
 /// Registers all controllers in the entry assembly which are marked with the MessageController attribute.
 /// </summary>
 /// <param name="builder"></param>
 public static ITapetiConfigBuilder RegisterAllControllers(this ITapetiConfigBuilder builder)
 {
     return(RegisterAllControllers(builder, Assembly.GetEntryAssembly()));
 }
Exemplo n.º 6
0
 /// <summary>
 /// Registers the transient publisher and required middleware
 /// </summary>
 /// <param name="config"></param>
 /// <param name="defaultTimeout"></param>
 /// <param name="dynamicQueuePrefix"></param>
 /// <returns></returns>
 public static ITapetiConfigBuilder WithTransient(this ITapetiConfigBuilder config, TimeSpan defaultTimeout, string dynamicQueuePrefix = "transient")
 {
     config.Use(new TransientExtension(defaultTimeout, dynamicQueuePrefix));
     return(config);
 }
Exemplo n.º 7
0
 /// <summary>
 /// Enables Tapeti Flow.
 /// </summary>
 /// <param name="config"></param>
 /// <param name="flowRepository">An optional IFlowRepository implementation to persist flow state. If not provided, flow state will be lost when the application restarts.</param>
 /// <returns></returns>
 public static ITapetiConfigBuilder WithFlow(this ITapetiConfigBuilder config, IFlowRepository flowRepository = null)
 {
     config.Use(new FlowExtension(flowRepository));
     return(config);
 }