Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autofac composite pattern

Tags:

c#

autofac

I noticed I quite often need to implement composite pattern. For example:

interface IService { ... }
class Service1 : IService { ... }
class Service2 : IService { ... }
class CompositeService : IService
{
    public CompositeService(IEnumerable<IService> services) { ... }
    ...
}

I want to register CompositeService as IService in container and have dependencies injected.

(looks somewhat similar to Decorator but decorating set of services instead of only one)

What's the best way to do it in autofac?

How would ideal solution look like (for C#)?

Update:

My current registration is:

builder.RegisterType<Service1>().Named<IService>("impl");
builder.RegisterType<Service2>().Named<IService>("impl");

builder.Register(c => new CompositeService(c.Resolve<IEnumerable<IService>>("impl")))
    .As<IService>();

It is similar to Decorators by Hand in http://nblumhardt.com/2011/01/decorator-support-in-autofac-2-4

Can it be improved?

like image 598
Konstantin Spirin Avatar asked Feb 23 '11 15:02

Konstantin Spirin


3 Answers

I haven't implemented this or even thought it through fully, but the best syntax I could achieve is:

builder
.RegisterComposite<IService>((c, elements) => new CompositeService(elements))
.WithElementsNamed("impl");

The elements parameter to the registration function would be of type IEnumerable<IService> and encapsulate the c.Resolve<IEnumerable<IService>>("impl").

Now how to write it...

like image 156
Bryan Watts Avatar answered Oct 03 '22 04:10

Bryan Watts


You could try named or keyed registrations. A named registration simply gets a string name, to differentiate it from other registrations of the same interface. Similarly, a key uses some value type, for instance an enum, to discriminate between multiple registrations. Your CompositeService would likely be the default reference, registered by type with no other special info needed. You'll need some method to resolve the other IService dependencies and pass them to the constructor; a factory method for CompositeService may work.

like image 26
KeithS Avatar answered Oct 03 '22 06:10

KeithS


Composite registration will be coming in AutoFac 6.0.

It won't automatically create a composite for you, but it will

  • inject all other implementations of the interface into the composite
  • register the composite as the default interface implementation
  • not resolve the composite in IEnumerable<Interface> resolutions.
like image 30
farlee2121 Avatar answered Oct 03 '22 04:10

farlee2121