jbogard / MediatR.Extensions.Microsoft.DependencyInjection

MediatR extensions for Microsoft.Extensions.DependencyInjection
MIT License
326 stars 90 forks source link

Add Source Generator service registration implementation #93

Open bbarry opened 3 years ago

bbarry commented 3 years ago

It would be nice to change the reflection done here to a compile time dependency. Instead of

services.AddMediatR(typeof(Startup).GetTypeInfo().Assembly);

we might add an attribute to our startup class and call a generated method:

[assembly:AddMediatRRegistrations(typeof(Startup))]

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddGenMediatR(); // <- method generated by source generators
    }
}

The former has significant and growing runtime costs associated as the complexity of the project increases, whereas the latter would generate a function

public static class MediatRGenerated
{
    public static IServiceCollection AddGenMediatR(this IServiceCollection services)
    {
        ServiceRegistrar.AddRequiredServices(services, ???);

        services.AddTransient(interface1, type1);
        services.AddTransient(interface2, type2);
        services.AddTransient(interface3, type3);
        services.AddTransient(interface4, type4);
        // ...
        return services;
    }
}

and thus not be subject to the for loop over assembliesToScan.SelectMany(a => a.DefinedTypes) multiple times (project I am working on was apparently looping over the defined types of all assemblies in the bin dir nearly 100 times for various libraries it was using).

jbogard commented 3 years ago

PRs are welcome :)

bbarry commented 3 years ago

heh, yeah I'm looking... probably wouldn't get to it for a while so if anybody else wants to try they are welcome.

I'm not really sure what the best approach is. C#9 source generators are implemented as roslyn analyzers, so in theory this project can be changed to an analyzer dependency instead of a runtime dependency (obviously this is a breaking change). Perhaps it would be better to implement it as a separate nuget package?

https://github.com/dotnet/roslyn/blob/master/docs/features/source-generators.md

Documentation for all this is still pretty sparse. I was also wondering if there was some interest in analyzers for mediatr you might know about?

martinothamar commented 3 years ago

Hey, I wondered about this myself, so a while back I created another mediator pattern implementation based on source generation myself: https://github.com/martinothamar/Mediator

There are some differences in API from MediatR but the source generation itself is maybe something to look at for a potential implementation here. It does assembly scanning to generate both DI extension method and the mediator implementation itself. Won't have time get into any PR here atm but posting this just in case someone else is considering it 😄