Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to register a new List<IChecker> to Autofac ContainerBuilder

Tags:

c#

autofac

      var servers = new List<IChecker> {
      //Server1
      new DatabaseSystem { ServerName = "ANTIVIRUS" },
      new DatabaseSizes  { ServerName = "ANTIVIRUS"},
      new DiskBackup { ServerName = "ANTIVIRUS"},
      new SqlServerEventLog { ServerName="ANTIVIRUS"},
      new DiskSystem { ServerName="ANTIVIRUS"}, 
      //Server1
      new DatabaseSystem { ServerName="SEJKG-S-DB01" },
      new DatabaseSizes  { ServerName = "SEJKG-S-DB01"},
      new DiskBackup { ServerName = "SEJKG-S-DB01"},
      new SqlServerEventLog { ServerName="SEJKG-S-DB01"},
      new DiskSystem { ServerName="SEJKG-S-DB01"},
  };

  var builder = new ContainerBuilder();            
  builder.RegisterInstance(notifiers).As<IList<INotifier>>();     
  builder.RegisterInstance(servers).As<IList<IChecker>>();
  builder.Register(c => new ServerChecker(c.Resolve<IList<IChecker>>(),  c.Resolve<IList<INotifier>>()));
  return builder.Build();

I have a problem with how I should register my "where server = new List {..} 'to the Container Builder. My List of iChecker passed as a parameter to a ServerChecker. So much have I been able to solve, but not the list itself but I must have outside. The usual list of servers is much greater.

like image 486
Johan Bertilsdotter Avatar asked Apr 20 '12 07:04

Johan Bertilsdotter


1 Answers

Autofac has implicit collection support such that you can register multiple individual items and when you resolve an IEnumerable of those items you will get all of the registrations:

var builder = new ContainerBuilder();
builder.RegisterType<FirstType>().As<IDependency>();
builder.RegisterType<SecondType>().As<IDependency>();
builder.RegisterType<ThirdType>().As<IDependency>();
var container = builder.Build();
using(var scope = container.BeginLifetimeScope())
{
  var allDependencies = scope.Resolve<IEnumerable<IDependency>>();
  // allDependencies will contain all three of the registered types.
}

This would allow you to greatly simplify the registrations since you wouldn't have to actually build the list ahead of time - you could just register each of your "IChecker" or "INotifier" instances directly and resolve the IEnumerable of them.

If you have the ability to change your "ServerChecker" constructor to take IEnumerable rather than IList, then you're done - you don't need to do the c.Resolve() thing anymore. That's possibly a better design anyway because IList implies the collection can be modified later, which is probably not what you want. (It may be that ServerChecker copies the contents of the IEnumerable into its own list so you could modify a local copy, but you wouldn't want folks to think they can or should modify the contents of the central dependency like that.)

If it has to be IList, you could add another registration that creates the list on the fly:

builder
  .Register(c => new List<IDependency>(c.Resolve<IEnumerable<IDependency>>()))
  .As<IList<IDependency>>();

That way you still can avoid doing the c.Resolve<...>() call in the resolution for the "ServerChecker" - Autofac will suddenly know about how to create the specific type of list.

If you really want to get fancy with it, you could add a custom Autofac RegistrationSource such that if anyone tries to resolve IList Autofac would automatically do the resolve of the IEnumerable and create a list... but that's a little more than you probably need.

like image 147
Travis Illig Avatar answered Nov 15 '22 21:11

Travis Illig