Search code examples
c#.netasp.net-mvcmodel-view-controllermediatr

Register all IMediatR classes


Is there any form to avoid registering all the assemblies that implement IMediator service?

I try using these options but none of them helps me:

builder.Services.AddMediatR(Assembly.GetExecutingAssembly());

builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()))

Currently the only option that works for me is if I register all the services like this:

builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(MYQUERY).Assembly));

But this is very tedious because my program.cs will have a lot of lines, is there any other option to do this?


Solution

  • But this is very tedious because my program.cs will have a lot of lines

    Personally I would go with the "manual" approach. If you don't want to "litter" the Program.cs then you can always move this part of the setup to some extension method:

    public static class MediatrRegistrationExts
    {
        public static IServiceCollection AddMediatorWithAll(this IServiceCollection services)
        {
            var types = new[]
            {
                typeof(MediatrAssemlyOneLandmark),
                typeof(MediatrAssemlyTwoLandmark)
            };
            services.AddMediatR(types.Select(t => t.Assembly).ToArray());
            return services;
        }
    } 
    

    And then:

    builder.Services.AddMediatorWithAll();
    

    But if you really-really want to go full dynamic mode then you can try something like the following (not tested):

    builder.Services.AddMediatR(GetAllAssemblies().ToArray());
    
    static IEnumerable<Assembly> GetAllAssemblies()
    {
        var assemblies = new HashSet<string>();
        var stack = new Stack<Assembly>();
    
        stack.Push(Assembly.GetEntryAssembly());
    
        while (stack.Count > 0)
        {
            var asm = stack.Pop();
    
            yield return asm;
    
            foreach (var reference in asm.GetReferencedAssemblies())
            {
                if (!assemblies.Contains(reference.FullName))
                {
                    stack.Push(Assembly.Load(reference));
                    assemblies.Add(reference.FullName);
                }
            }
    
        }
    }
    

    But I highly recommend against it.

    P.S.

    Make sure that you have actually those types placed in different assemblies because based on the comments it is highly likely they are actually in a single assembly.