0

My problem is a variation on this one: Unity Register two interfaces as one singleton

In my case the injected singleton component has two interfaces, but one of those interfaces is used to map multiple named concrete types.

For example, my Component requires as dependencies, a set of (named) IEventSources and a single IEventManager (which itself is also an IEventSource):

  public interface IEventManager { }

  public interface IEventSource { }

  public class EventManager : IEventManager, IEventSource { }

  public class EventSourceA : IEventSource { }

  public class EventSourceB : IEventSource { }

  public class Component
  {
    public Component(IEventManager eventManager, IEventSource[] eventSources)
    {
      Debug.Assert(eventSources.Contains((IEventSource) eventManager));
    }
  }

  class Program
  {
    static void Main()
    {
      var container = new UnityContainer();
      container.RegisterType<IEventManager, EventManager>(new ContainerControlledLifetimeManager());
      container.RegisterType<IEventSource, EventManager>("EventManager", new ContainerControlledLifetimeManager());
      container.RegisterType<IEventSource, EventSourceA>("EventSourceA");
      container.RegisterType<IEventSource, EventSourceB>("EventSourceB");
      container.RegisterType(typeof(Component));

      container.Resolve<Component>();
    }
  }

Or, as I ultimately need to configure this from app.config:

  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <container>
      <register type="IEventManager" mapTo="EventManager">
        <lifetime type="singleton" />
      </register>
      <register name="EventManager" type="IEventSource" mapTo="EventManager">
        <lifetime type="singleton" />
      </register>
      <register name="EventSourceA" type="IEventSource" mapTo="EventSourceA" />
      <register name="EventSourceB" type="IEventSource" mapTo="EventSourceB" />
      <register type="Component" />
    </container>
  </unity>

Here two EventManager instances are created, and the assertion fails. I want to ensure that the same instance satisfies both Component dependencies.

I can have the component accept only the IEventSource instances, and at runtime pull out from that set the single IEventManager instance, but that seems brittle and smells bad to me. Is there a way to pull this off with Unity?

Community
  • 1
  • 1
lesscode
  • 6,221
  • 30
  • 58

1 Answers1

1

if you change your registration code within Main like below, you assert will pass. Would it suffice?

        var container = new UnityContainer();

        var manager = container.Resolve<EventManager>();
        container.RegisterInstance<IEventManager>(manager, new ContainerControlledLifetimeManager());
        container.RegisterInstance<IEventSource>("EventManager", manager, new ContainerControlledLifetimeManager());

        container.RegisterType<IEventSource, EventSourceA>("EventSourceA");
        container.RegisterType<IEventSource, EventSourceB>("EventSourceB");
        container.RegisterType(typeof(Component));

        container.Resolve<Component>();
anikiforov
  • 495
  • 6
  • 19
  • I ultimately need to configure the container from the app.config file - is the above possible from config? – lesscode Mar 08 '13 at 16:23
  • Unfortunately you can't do the same thing in the config file without writing custom UnityContainerExtension, and probably custom IDependencyResolver. – anikiforov Mar 09 '13 at 09:39
  • [Take a look here](http://www.chrisvandesteeg.nl/2009/04/16/making-unity-work-more-like-the-others/) to get the idea how the code of the custom extension looks like. Having to write your custom extension might be an overkill compared to simply doing this particular registration in code, but that ultimately depends on why you need to put this registration in the config file. – anikiforov Mar 09 '13 at 09:46
  • OK, thanks - I'll look into extending Unity. This is a service architecture with an extensibility point to plug in custom event sources and event sinks, so I want to avoid as much runtime configuration code as possible. – lesscode Mar 10 '13 at 16:06