Search code examples
c#modulecontainersautofac

Autofac list merging in C#


I am dealing with some issues merging List items together. Let me try to explain.

I have a common Autofac Container. Now imagine I have two modules (Module1 and Module2). In Module1 I have registered an object which looks somehow like this (pseudo-code):

builder.Register( context =>
                       {
                               Configuration someConf= new Configuration( "https://+:20303",
                                                                                       null,
                                                                                       "/temp",
                                                                                       true,
                                                                                       true );

                               someConf.AutofacContext = context;
                               someConf.Types.Add( context.ResolveKeyed<Type>( "Type1" ) ); //I have registered these types before
                               someConf.Types.Add( context.ResolveKeyed<Type>("Type2") );

                               return someConf;
                           } )
                          .Keyed<Configuration>( "Object1" )
                          .SingleInstance();

Now imagine I have a Module2 where I want to get this object, add some new Types into the list and go on with the functionality. I understand that autofac should override the objects with the same attributes. Of course I would love to have these new Types in the Module1 as well. Is there any possible way to do it?

Thanks a lot.


Solution

  • Instead of trying to merge elements you can introduce a IConfigurationProvider interface

    public interface IConfigurationProvider 
    {
         IEnumerable<Type> GetInstances();
    }
    

    On each module you can implement this interface

    and then on the core of your application you can resolve a IEnumerable<IConfigurationProvider> and register your config

    builder.Register(ctx => {
        var conf = new Configuration( ...
        var instances = ctx.Resolve<IEnumerable<IConfigurationProvider>>()
                           .SelectMany(cp => cp.GetInstances()); 
        conf.Types.AddRange(instances);
    
        return conf;
    })
    .Keyed<Configuration>( "Object1" )
    .SingleInstance();
    

    You can also register a keyed IEnumerable<XType> if you want to avoid having a new interface

     builder.Register(ctx => {
        return new []{
            ctx.ResolveKeyed<XType>("type1"),
            ctx.ResolveKeyed<XType>("type2"),
        }
     })
     .Keyed<IEnumerable<XType>>("configurationElements")
     .SingleInstance();  
    

    and then

    builder.Register(ctx => {
        var conf = new Configuration( ...
        var instances = ctx.ResolveKeyed<IEnumerable<IEnumerable<Type>>>("configurationElements")
                           .SelectMany(cp => cp); 
        conf.Types.AddRange(instances);
    
        return conf;
    })
    .Keyed<Configuration>( "Object1" )
    .SingleInstance();