public static IConveyBuilder AddInfrastructure(this IConveyBuilder builder) { // Recordings builder.Services.AddTransient <IRecordingRepository, RedisRecordingRepository>(); builder.Services.AddSingleton <IAuthorizationHandler, HasScopeHandler>(); builder.Services.AddAuthorization(options => { options.AddPolicy(PlaybackScopes.READ_PAYLOAD, policyBuilder => policyBuilder.Requirements.Add( new HasScopeRequirement(PlaybackScopes.READ_PAYLOAD, "https://prometric.oktapreview.com/oauth2/ausu831293IEbvvD21d5"))); options.AddPolicy(PlaybackScopes.WRITE_PAYLOAD, policyBuilder => policyBuilder.Requirements.Add( new HasScopeRequirement(PlaybackScopes.WRITE_PAYLOAD, "https://prometric.oktapreview.com/oauth2/ausu831293IEbvvD21d5"))); }); return(builder .AddErrorHandler <ExceptionToResponseMapper>() .AddJwt() .AddQueryHandlers() .AddInMemoryQueryDispatcher() .AddHandlersLogging() .AddHttpClient() .AddMetrics() .AddRedis() .AddWebApiSwaggerDocs()); }
public static IConveyBuilder AddConsul(this IConveyBuilder builder, Func <IConsulOptionsBuilder, IConsulOptionsBuilder> buildOptions, HttpClientOptions httpClientOptions) { var options = buildOptions(new ConsulOptionsBuilder()).Build(); return(builder.AddConsul(options, httpClientOptions)); }
public static IConveyBuilder AddExceptionToMessageMapper <T>(this IConveyBuilder builder) where T : class, IExceptionToMessageMapper { builder.Services.AddTransient <IExceptionToMessageMapper, T>(); return(builder); }
public static IConveyBuilder AddSwaggerDocs(this IConveyBuilder builder, SwaggerOptions options) { if (!options.Enabled || !builder.TryRegister(RegistryName)) { return(builder); } builder.Services.AddSingleton(options); builder.Services.AddSwaggerGen(c => { c.SwaggerDoc(options.Name, new OpenApiInfo { Title = options.Title, Version = options.Version }); if (options.IncludeSecurity) { c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.ApiKey }); } }); return(builder); }
public static IConveyBuilder AddMongo(this IConveyBuilder builder, Func <IMongoDbOptionsBuilder, IMongoDbOptionsBuilder> buildOptions, IMongoDbSeeder seeder = null) { var mongoOptions = buildOptions(new MongoDbOptionsBuilder()).Build(); return(builder.AddMongo(mongoOptions, seeder)); }
public static IConveyBuilder AddWebApi(this IConveyBuilder builder, string sectionName = SectionName) { if (!builder.TryRegister(RegistryName)) { return(builder); } builder.Services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>(); builder.Services.AddSingleton(new WebApiEndpointDefinitions()); builder.Services.AddRouting() .AddLogging() .AddMvcCore() .AddJsonFormatters() .AddDataAnnotations() .AddApiExplorer() .AddDefaultJsonOptions() .AddAuthorization(); builder.Services.Scan(s => s.FromAssemblies(AppDomain.CurrentDomain.GetAssemblies()) .AddClasses(c => c.AssignableTo(typeof(IRequestHandler <,>))) .AsImplementedInterfaces() .WithTransientLifetime()); builder.Services.AddTransient <IRequestDispatcher, RequestDispatcher>(); return(builder); }
public static IConveyBuilder AddErrorHandling(this IConveyBuilder builder) { builder.Services.AddTransient <IExceptionCompositionRoot, ExceptionCompositionRoot>(); builder.Services.AddSingleton <IExceptionToResponseMapper, DefaultExceptionToResponseMapper>(); return(builder); }
private static void AddModuleRegistry(this IConveyBuilder builder) { var eventTypes = AppDomain.CurrentDomain .GetAssemblies() .Where(a => a.FullName.Contains("Cine")) .SelectMany(a => a.GetTypes()) .Where(t => t.IsClass && typeof(IEvent).IsAssignableFrom(t)) .ToList(); builder.Services.AddSingleton <IModuleRegistry>(provider => { var logger = provider.GetService <ILogger <IModuleRegistry> >(); var registry = new ModuleRegistry(logger); foreach (var type in eventTypes) { registry.AddBroadcastAction(type, (sp, @event) => { var dispatcher = sp.GetService <IEventDispatcher>(); return((Task)dispatcher.GetType() .GetMethod(nameof(dispatcher.PublishAsync)) .MakeGenericMethod(type) .Invoke(dispatcher, new[] { @event })); }); } return(registry); }); }
public static IConveyBuilder AddOcsClient(this IConveyBuilder builder, string sectionName = SectionName) { if (string.IsNullOrEmpty(sectionName)) { sectionName = SectionName; } var ocsOptions = builder.GetOptions <OcsOptions>(sectionName); if (string.IsNullOrEmpty(ocsOptions.InternalHttpClientName)) { ocsOptions.InternalHttpClientName = "OcsClient"; } builder.Services.AddSingleton(ocsOptions); builder.Services.AddHttpClient(ocsOptions.InternalHttpClientName, c => { c.BaseAddress = new Uri(ocsOptions.StorageUrl); c.DefaultRequestHeaders.UserAgent.Add(ProductInfoHeaderValue.Parse("OcsClient")); c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json)); }); builder.Services.AddTransient <IRequestHandler, RequestHandler.RequestHandler>(); builder.Services.AddTransient <IOcsClient, OcsClient>(); builder.Services.AddTransient <IAuthManager, AuthManager>(); return(builder); }
public static IConveyBuilder AddInfrastructure(this IConveyBuilder builder) { builder.Services .AddSingleton <IRequestStorage, RequestStorage>() .AddSingleton <IStoryRequestStorage, StoryRequestStorage>() .AddSingleton <IIdGenerator, IdGenerator>() .AddSingleton <RequestTypeMetricsMiddleware>() .AddSingleton <IClock, UtcClock>() .AddScoped <IMessageBroker, MessageBroker>() .AddScoped <IStoryRepository, StoryMongoRepository>() .AddScoped <IStoryRatingRepository, StoryRatingMongoRepository>() .AddScoped <IUserRepository, UserMongoRepository>() .AddScoped <IUsersApiClient, UsersApiHttpClient>() .AddTransient <IAppContextFactory, AppContextFactory>() .AddTransient(ctx => ctx.GetRequiredService <IAppContextFactory>().Create()) .AddDomainEvents() .AddGrpc(); if (builder.GetOptions <PrometheusOptions>("prometheus").Enabled) { builder.Services.TryDecorate(typeof(ICommandHandler <>), typeof(MetricsCommandHandlerDecorator <>)); } if (builder.GetOptions <JaegerOptions>("jaeger").Enabled) { builder.Services.TryDecorate(typeof(ICommandHandler <>), typeof(TracingCommandHandlerDecorator <>)); } builder.Services.TryDecorate(typeof(ICommandHandler <>), typeof(LoggingCommandHandlerDecorator <>)); builder.Services.TryDecorate(typeof(IEventHandler <>), typeof(LoggingEventHandlerDecorator <>)); builder.Services.TryDecorate(typeof(ICommandHandler <>), typeof(OutboxCommandHandlerDecorator <>)); builder.Services.TryDecorate(typeof(IEventHandler <>), typeof(OutboxEventHandlerDecorator <>)); builder .AddErrorHandler <ExceptionToResponseMapper>() .AddExceptionToMessageMapper <ExceptionToMessageMapper>() .AddQueryHandlers() .AddInMemoryQueryDispatcher() .AddHttpClient() .AddConsul() .AddFabio() .AddRabbitMq(plugins: p => p.AddJaegerRabbitMqPlugin()) .AddMessageOutbox(o => o.AddMongo()) .AddMongo() .AddRedis() .AddPrometheus() .AddJaeger() .AddMongoRepository <StoryDocument, long>("stories") .AddMongoRepository <UserDocument, Guid>("users") .AddWebApiSwaggerDocs() .AddCertificateAuthentication() .AddSecurity(); builder.Services.AddScoped <LogContextMiddleware>() .AddSingleton <ICorrelationIdFactory, CorrelationIdFactory>(); return(builder); }
public static IConveyBuilder AddInfrastructure(this IConveyBuilder builder) { var requestsOptions = builder.GetOptions <RequestsOptions>("requests"); builder.Services.AddSingleton(requestsOptions); builder.Services.AddTransient <ICommandHandler <ICommand>, GenericCommandHandler <ICommand> >() .AddTransient <IEventHandler <IEvent>, GenericEventHandler <IEvent> >() .AddTransient <IEventHandler <IRejectedEvent>, GenericRejectedEventHandler <IRejectedEvent> >() .AddTransient <IHubService, HubService>() .AddTransient <IHubWrapper, HubWrapper>() .AddSingleton <IOperationsService, OperationsService>(); builder.Services.AddGrpc(); return(builder .AddErrorHandler <ExceptionToResponseMapper>() .AddJwt() .AddCommandHandlers() .AddEventHandlers() .AddQueryHandlers() .AddHttpClient() .AddConsul() .AddFabio() .AddRabbitMq(plugins: p => p.AddJaegerRabbitMqPlugin()) .AddMongo() .AddRedis() .AddMetrics() .AddJaeger() .AddRedis() .AddSignalR() .AddWebApiSwaggerDocs() .AddSecurity()); }
public static IConveyBuilder AddInfrastructure(this IConveyBuilder builder) { builder.Services.AddSingleton <IEventMapper, EventMapper>(); builder.Services.AddTransient <ITripRepository, TripsMongoRepository>(); builder.Services.AddTransient <IMessageBroker, MessageBroker>(); builder.Services.AddTransient <IEventProcessor, EventProcessor>(); builder.Services.Scan(s => s.FromAssemblies(AppDomain.CurrentDomain.GetAssemblies()) .AddClasses(c => c.AssignableTo(typeof(IDomainEventHandler <>))) .AsImplementedInterfaces() .WithTransientLifetime()); builder .AddQueryHandlers() .AddInMemoryQueryDispatcher() .AddErrorHandler <ExceptionToResponseMapper>() .AddExceptionToMessageMapper <ExceptionToMessageMapper>() .AddMongo() .AddMongoRepository <TripDocument, Guid>("trips") .AddRabbitMq() .AddSwaggerDocs() .AddWebApiSwaggerDocs(); return(builder); }
public static IConveyBuilder AddMetrics(this IConveyBuilder builder, Func <IMetricsOptionsBuilder, IMetricsOptionsBuilder> buildOptions) { var options = buildOptions(new MetricsOptionsBuilder()).Build(); return(builder.AddMetrics(options)); }
public static IConveyBuilder AddApplication(this IConveyBuilder builder) { return(builder.AddCommandHandlers() .AddEventHandlers() .AddInMemoryCommandDispatcher() .AddInMemoryEventDispatcher()); }
private static IConveyBuilder AddJwt(this IConveyBuilder builder, JwtOptions options, Action <IConveyBuilder> registerRedis) { if (!builder.TryRegister(RegistryName)) { return(builder); } registerRedis(builder); builder.Services.AddSingleton(options); builder.Services.AddSingleton <IJwtHandler, JwtHandler>(); builder.Services.AddTransient <IAccessTokenService, AccessTokenService>(); builder.Services.AddTransient <AccessTokenValidatorMiddleware>(); builder.Services.AddAuthentication() .AddJwtBearer(cfg => { cfg.TokenValidationParameters = new TokenValidationParameters { IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(options.SecretKey)), ValidIssuer = options.Issuer, ValidAudience = options.ValidAudience, ValidateAudience = options.ValidateAudience, ValidateLifetime = options.ValidateLifetime }; }); return(builder); }
public static IConveyBuilder AddConsul(this IConveyBuilder builder, ConsulOptions options, HttpClientOptions httpClientOptions) { builder.Services.AddSingleton(options); if (!options.Enabled || !builder.TryRegister(RegistryName)) { return(builder); } if (httpClientOptions.Type?.ToLowerInvariant() == "consul") { builder.Services.AddTransient <ConsulServiceDiscoveryMessageHandler>(); builder.Services.AddHttpClient <IConsulHttpClient, ConsulHttpClient>("consul-http") .AddHttpMessageHandler <ConsulServiceDiscoveryMessageHandler>(); builder.RemoveHttpClient(); builder.Services.AddHttpClient <IHttpClient, ConsulHttpClient>("consul") .AddHttpMessageHandler <ConsulServiceDiscoveryMessageHandler>(); } builder.Services.AddTransient <IConsulServicesRegistry, ConsulServicesRegistry>(); var registration = builder.CreateConsulAgentRegistration(options); if (registration is null) { return(builder); } builder.Services.AddSingleton(registration); return(builder); }
private static IConveyBuilder AddServiceClient <T>(this IConveyBuilder builder, string serviceName, RestEaseOptions options, Action <IConveyBuilder> registerFabio) where T : class { if (!builder.TryRegister(RegistryName)) { return(builder); } var clientName = typeof(T).ToString(); switch (options.LoadBalancer?.ToLowerInvariant()) { case "consul": builder.AddConsulHttpClient(clientName, serviceName); break; case "fabio": builder.AddFabioHttpClient(clientName, serviceName); break; default: ConfigureDefaultClient(builder.Services, clientName, serviceName, options); break; } ConfigureForwarder <T>(builder.Services, clientName); registerFabio(builder); return(builder); }
public static IConveyBuilder AddInfrastructure(this IConveyBuilder builder) { builder.Services.AddTransient <IMessageBroker, MessageBroker>(); builder.Services.AddTransient <ICourseRepository, CourseRepository>(); builder.Services.AddTransient <ICourseModuleRepository, CourseModuleRepository>(); builder.Services.AddTransient <ICourseEpisodeRepository, CourseEpisodeRepository>(); builder.Services.AddSingleton <IDateTimeProvider, DateTimeProvider>(); builder.Services.AddTransient <IAppContextFactory, AppContextFactory>(); builder.Services.AddTransient(ctx => ctx.GetRequiredService <IAppContextFactory>().Create()); builder.Services.TryDecorate(typeof(ICommandHandler <>), typeof(OutboxCommandHandlerDecorator <>)); builder.Services.TryDecorate(typeof(IEventHandler <>), typeof(OutboxEventHandlerDecorator <>)); return(builder .AddErrorHandler <ExceptionToResponseMapper>() .AddQueryHandlers() .AddInMemoryQueryDispatcher() .AddHttpClient() .AddConsul() .AddFabio() .AddRabbitMq(plugins: p => p.AddJaegerRabbitMqPlugin()) .AddMessageOutbox(o => o.AddMongo()) .AddExceptionToMessageMapper <ExceptionToMessageMapper>() .AddMongo() .AddRedis() .AddMetrics() .AddJaeger() .AddMongoRepository <CourseDocument, Guid>("courses") .AddMongoRepository <CourseModuleDocument, Guid>("courseModules") .AddMongoRepository <CourseEpisodeDocument, Guid>("courseEpisodes") .AddWebApiSwaggerDocs()); }
public static IConveyBuilder AddInfrastructure(this IConveyBuilder builder) { builder.Services.AddTransient <IMessageBroker, MessageBroker>(); builder.Services.AddTransient <ISprintRepository, SprintRepository>(); builder.Services.AddTransient <IProjectRepository, ProjectRepository>(); builder.Services.AddTransient <IIssueRepository, IssueRepository>(); builder.Services.AddTransient <IAppContextFactory, AppContextFactory>(); builder.Services.AddTransient <IIdentityApiHttpClient, IdentityApiHttpClient>(); builder.Services.AddTransient(ctx => ctx.GetRequiredService <IAppContextFactory>().Create()); builder.Services.TryDecorate(typeof(ICommandHandler <>), typeof(OutboxCommandHandlerDecorator <>)); builder.Services.TryDecorate(typeof(IEventHandler <>), typeof(OutboxEventHandlerDecorator <>)); return(builder .AddErrorHandler <ExceptionToResponseMapper>() .AddQueryHandlers() .AddInMemoryQueryDispatcher() .AddJwt() .AddHttpClient() .AddConsul() .AddFabio() .AddExceptionToMessageMapper <ExceptionToMessageMapper>() .AddRabbitMq(plugins: p => p.AddJaegerRabbitMqPlugin()) .AddMessageOutbox(o => o.AddMongo()) .AddMongo() .AddRedis() .AddJaeger() .AddMongoRepository <IssueDocument, string>("issues") .AddMongoRepository <ProjectDocument, string>("projects") .AddMongoRepository <SprintDocument, string>("sprints") .AddWebApiSwaggerDocs() .AddSecurity()); }
public static IConveyBuilder AddRedis(this IConveyBuilder builder, Func <IRedisOptionsBuilder, IRedisOptionsBuilder> buildOptions) { var options = buildOptions(new RedisOptionsBuilder()).Build(); return(builder.AddRedis(options)); }
public static IConveyBuilder AddSwaggerDocs(this IConveyBuilder builder, Func <ISwaggerOptionsBuilder, ISwaggerOptionsBuilder> buildOptions) { var options = buildOptions(new SwaggerOptionsBuilder()).Build(); return(builder.AddSwaggerDocs(options)); }
public static IConveyBuilder RegisterConvey(this IConveyBuilder builder, IConfiguration configuration) { var uniqueId = Assembly.GetEntryAssembly().GetName().Name; //Consult /* * var consulOptions = new ConsulOptions(); * configuration.GetSection("External::consult").Bind(consulOptions); * * //Fabio * var fabioOptions = new FabioOptions(); * configuration.GetSection(FabioSectionName).Bind(fabioOptions); * * * var httpClientOptions = builder.GetOptions<HttpClientOptions>(HttpClientSectionName); * * consulOptions.Service = uniqueId.ToLower(); * fabioOptions.Service = uniqueId.ToLower(); * * builder * .AddHttpClient() * .AddConsul(consulOptions, httpClientOptions) * .AddFabio(fabioOptions, consulOptions, httpClientOptions); */ builder .AddHttpClient() .AddConsul() .AddFabio(); return(builder); }
public static IConveyBuilder AddMongo(this IConveyBuilder builder, string sectionName = SectionName, IMongoDbSeeder seeder = null) { var mongoOptions = builder.GetOptions <MongoDbOptions>(sectionName); return(builder.AddMongo(mongoOptions, seeder)); }
public static IConveyBuilder AddJaeger(this IConveyBuilder builder, Func <IJaegerOptionsBuilder, IJaegerOptionsBuilder> buildOptions) { var options = buildOptions(new JaegerOptionsBuilder()).Build(); return(builder.AddJaeger(options)); }
public static IConveyBuilder AddInfrastructure(this IConveyBuilder builder) { builder.Services.AddSingleton <IJwtProvider, JwtProvider>(); builder.Services.AddSingleton <IPasswordService, PasswordService>(); builder.Services.AddSingleton <IPasswordHasher <IPasswordService>, PasswordHasher <IPasswordService> >(); builder.Services.AddTransient <IIdentityService, IdentityService>(); builder.Services.AddTransient <IRefreshTokenService, RefreshTokenService>(); builder.Services.AddSingleton <IRng, Rng>(); builder.Services.AddTransient <IMessageBroker, MessageBroker>(); builder.Services.AddTransient <IRefreshTokenRepository, RefreshTokenRepository>(); builder.Services.AddTransient <IUserRepository, UserRepository>(); builder.Services.AddTransient <IAppContextFactory, AppContextFactory>(); builder.Services.AddTransient(ctx => ctx.GetRequiredService <IAppContextFactory>().Create()); builder.Services.TryDecorate(typeof(ICommandHandler <>), typeof(OutboxCommandHandlerDecorator <>)); builder.Services.TryDecorate(typeof(IEventHandler <>), typeof(OutboxEventHandlerDecorator <>)); return(builder .AddErrorHandler <ExceptionToResponseMapper>() .AddQueryHandlers() .AddInMemoryQueryDispatcher() .AddJwt() .AddHttpClient() .AddConsul() .AddFabio() .AddExceptionToMessageMapper <ExceptionToMessageMapper>() .AddRabbitMq(plugins: p => p.AddJaegerRabbitMqPlugin()) .AddMessageOutbox(o => o.AddMongo()) .AddMongo() .AddRedis() .AddMetrics() .AddJaeger() .AddMongoRepository <RefreshTokenDocument, Guid>("refreshTokens") .AddMongoRepository <UserDocument, Guid>("users") .AddWebApiSwaggerDocs()); }
public static IConveyBuilder AddInfrastructure(this IConveyBuilder builder) { builder.Services.AddSingleton <IEventMapper, EventMapper>(); builder.Services.AddTransient <IMessageBroker, MessageBroker>(); builder.Services.AddTransient <ICustomerRepository, CustomerMongoRepository>(); builder.Services.AddTransient <IOrderRepository, OrderMongoRepository>(); builder.Services.AddSingleton <IDateTimeProvider, DateTimeProvider>(); builder.Services.AddTransient <IParcelsServiceClient, ParcelsServiceClient>(); builder.Services.AddTransient <IPricingServiceClient, PricingServiceClient>(); builder.Services.AddTransient <IVehiclesServiceClient, VehiclesServiceClient>(); builder.Services.AddTransient <IAppContextFactory, AppContextFactory>(); builder.Services.AddTransient(ctx => ctx.GetRequiredService <IAppContextFactory>().Create()); return(builder .AddQueryHandlers() .AddInMemoryQueryDispatcher() .AddHttpClient() .AddConsul() .AddFabio() .AddRabbitMq <CorrelationContext>(plugins: p => p.RegisterJaeger()) .AddExceptionToMessageMapper <ExceptionToMessageMapper>() .AddMongo() .AddMetrics() .AddJaeger() .AddHandlersLogging() .AddMongoRepository <CustomerDocument, Guid>("Customers") .AddMongoRepository <OrderDocument, Guid>("Orders")); }
public static IConveyBuilder AddMongo(this IConveyBuilder builder, Func <IMongoDbOptionsBuilder, IMongoDbOptionsBuilder> buildOptions, Type seederType = null, bool registerConventions = true) { var mongoOptions = buildOptions(new MongoDbOptionsBuilder()).Build(); return(builder.AddMongo(mongoOptions, seederType, registerConventions)); }
public static IConveyBuilder AddInfrastructure(this IConveyBuilder builder) { builder.Services.AddSingleton <IDateTimeProvider, DateTimeProvider>(); builder.Services.AddTransient <IMessageBroker, MessageBroker>(); builder.Services.AddTransient <IUserRepository, UserMongoRepository>(); builder.Services.AddTransient <IAppContextFactory, AppContextFactory>(); builder.Services.AddTransient(ctx => ctx.GetRequiredService <IAppContextFactory>().Create()); builder.Services.TryDecorate(typeof(ICommandHandler <>), typeof(OutboxCommandHandlerDecorator <>)); builder.Services.TryDecorate(typeof(IEventHandler <>), typeof(OutboxEventHandlerDecorator <>)); return(builder .AddQueryHandlers() .AddInMemoryQueryDispatcher() .AddHttpClient() .AddConsul() .AddFabio() .AddRabbitMq(plugins: p => p.AddJaegerRabbitMqPlugin()) .AddMessageOutbox(o => o.AddMongo()) .AddMongo() .AddRedis() .AddMetrics() .AddJaeger() .AddJaegerDecorators() .AddHandlersLogging() .AddMongoRepository <UserDocument, Guid>("identity")); }
public static IConveyBuilder AddInfrastructure(this IConveyBuilder builder) { builder.Services .AddSingleton <IHttpContextAccessor, HttpContextAccessor>() .AddTransient <IStorage, RedisStorage>(); builder .AddCommandHandlers() .AddEventHandlers() .AddInMemoryCommandDispatcher() .AddInMemoryEventDispatcher() .AddQueryHandlers() .AddInMemoryQueryDispatcher() .AddJwt() .AddHttpClient() .AddConsul() .AddFabio() .AddRabbitMq(plugins: p => p.AddJaegerRabbitMqPlugin()) .AddRedis() .AddPrometheus() .AddJaeger() .AddWebApiSwaggerDocs() .AddSecurity(); builder.Services.AddScoped <LogContextMiddleware>() .AddSingleton <ICorrelationIdFactory, CorrelationIdFactory>(); builder.Services.TryDecorate(typeof(ICommandHandler <>), typeof(LoggingCommandHandlerDecorator <>)); builder.Services.TryDecorate(typeof(IEventHandler <>), typeof(LoggingEventHandlerDecorator <>)); return(builder); }
public static IConveyBuilder AddApplication(this IConveyBuilder builder) => builder // .AddCommandHandlers() .AddEventHandlers() // .AddInMemoryCommandDispatcher() .AddInMemoryEventDispatcher();