Skip to content

Latest commit

 

History

History
167 lines (116 loc) · 4.39 KB

File metadata and controls

167 lines (116 loc) · 4.39 KB

Logo

Notorious Modules provide a simple way to separate monolith into standalone modules.

Summary

Support

  • Net8+

Features

  • Modules separation
  • Automatic injection
  • Global endpoints configuration
  • Easy modular monolith architecture
  • Based on net minimal apis

Motivation

The goal is to provide a way to separate applications into modules that can be moved at anytime without any pain. Based on Module monolith architecture.

Getting Started

First, install NuGet. Then, install NotoriousTest from the package manager console:

PM> Install-Package NotoriousModules

Or from the .NET CLI as:

dotnet add package NotoriousModules

Modules

What is a module ?

A module can be seen as an independent components with well-defined functionnal boundaries. It group together related functionnalities.

For example, in a basic e-commerce applications, we could have a modules for invoices functionnalities, orders, users, and cart.

img

How to implement modules

Notorious Modules provide a base class for modules :

public class ExampleModule : NotoriousModules.Modules
{
    public override string ModuleName => "Example";

    public ExampleModule() : base()
    {
    }

    protected override void ConfigureModuleEndpoints(RouteGroupBuilder routeGroupBuilder)
    {
        base.ConfigureModuleEndpoints(routeGroupBuilder);

		// Here you can configure your endpoints
		AddPostEndpoint("orders", async ([FromServices] GetOrdersFeature feature, [FromBody] GetOrdersParams @params) =>
		{
			return await feature.Handle(@params);
		});

    }

    protected override void ConfigureDependencyInjection(IServiceCollection services, IConfiguration configuration)
    {
        base.ConfigureDependencyInjection(services, configuration);
		// Here you can configure your dependency injection.
    }

    protected override void ConfigureApp(WebApplication app)
    {
		base.ConfigureApp(app);
		// Here you can configure your middlewares
    }

	protected override void ConfigureEachEndpoint(IEndpointConventionBuilder routeHandlerBuilder)
	{
		base.ConfigureEachEndpoint(routeHandlerBuilder);

		// Here you can configure every endpoint.
		// For example, lets configure OpenApi :
		routeHandlerBuilder
			.WithTags(ModuleName)
			.WithOpenApi();
	}
}

Module provide several method that u could override.

Use ConfigureModuleEndpoints with AddEndpoint, AddPostEndpoint, AddGetEndpoint, AddPutEndpoint, AddDeleteEndpoint or AddPatchEndpoint to configure your minimal apis.

Use ConfigureDependencyInjection to configure the application injection container.

Use ConfigureApp to configure modules middlewares.

Use ConfigureEachEndpoint to configure every endpoint of a module.

Configure application to use modules

In your Program.cs, you will need to register every modules :

// IServiceCollection AddModules(this IServiceCollection services, IConfiguration configuration, params Assembly[] assemblies)
builder.Services.AddModules(builder.Configuration, Orders.AssemblyMarker.Get(), Cart.AssemblyMarker.Get());

Pass-in assemblies that contains modules, they will be automatically retrieved and used.

:information: You can't add constructor parameters to modules.

Then, you just need to use theses modules :

var app = builder.Build();
app.UseModules();

And that's it, now u can create an infinite number of modules or extend module to create your own base modules.

For example, here's one module that integrate Swagger UI :

public abstract class OpenApiModule : Module
{
    public OpenApiModule() : base()
    {
    }


    protected override void ConfigureEachEndpoint(IEndpointConventionBuilder routeHandlerBuilder)
    {
        base.ConfigureEachEndpoint(routeHandlerBuilder);

        routeHandlerBuilder
            .WithTags(ModuleName)
            .WithOpenApi();
    }
}

public class ExampleModule : NotoriousModules.OpenApiModule
{
    public override string ModuleName => "Example";

    public ExampleModule() : base()
    {
    }

    ...
}