3

I have the following problem. I have two classes T1 and T2 that both implement interface T. I'd like T2 to decorate T1 so when I create an instance of T T2 is called first, then T1.

public class T1 : IT
{
    public void Call()
    {
        Write("T1");
    }
}

public class T2 : IT
{
    private IT _t;

    public T2(ISomeOther other, IT t)
    {
        _t = t;
    }

    public void Call()
    {
        Write("T2");
        _t.Call();
    }
}

public interface T {
    void Call();
}

My unity looks like this:

var unityContainer = new UnityContainer();
unityContainer.RegisterType<ISomeOther>(new Other());
unityContainer.RegisterType<T>(new T1());
unityContainer.RegisterType<T, T2>(new InjectionConstructor(new ResolvedParameter<ISomeOther>(), new ResolvedParameter<T2>());

I'd like to avoid having to explicitly spell out ResolvedParameters - the whole purpose in Unity is to remove this sort of work. I'd like to simply tell Unity that T2 decorates T1, and have Unity resolve the arguments. I'd have liked my final line of code to like to look something like this:

unityContainer.RegisterType<T, T2>().Decorates<T1>();

Is such a thing possible in Unity? Are there other IoC containers that are better for this sort of thing?

Note this is a simplified example so any minor syntax errors are incidental.

Edit:

This is not a duplicate of How do I use the Decorator Pattern with Unity without explicitly specifying every parameter in the InjectionConstructor - I DO NOT WANT TO EXPLICITLY CREATE THE DECORATOR OR LIST OUT THE DEPENDENCIES. Like this:

_container.Register<IT, T1>();
_container.Decorate<IT, T2>();
_container.Decorate<IT, T3>();

Where T1, T2 and T3 may have various dependencies in the constructor - I don't want to list these out, I want the IoC container to resolve these for me (otherwise why use an IoC container at all?)

Community
  • 1
  • 1
garryp
  • 5,508
  • 1
  • 29
  • 41
  • Did you mean initialize T2 with instance of T1? It's little mixed up in your example (InjectionConstructor takes T2 as implementation of T instead of T1?). – mwilczynski May 06 '15 at 14:45
  • Yes, T2 should be called first, then T1. T2 should decorate T1, adding services if required. I've updated the code to show T2 invoking a method on T1 (coded against the interface). In practice several of this may be chained together. – garryp May 06 '15 at 15:03
  • Related: https://stackoverflow.com/questions/6109646/how-do-i-use-the-decorator-pattern-with-unity-without-explicitly-specifying-ever – Steven May 06 '15 at 19:55
  • Check out this answer which defines an alternative InjectionConstructor to allow you to specify a subset of the constructor parameters and it will figure out the rest: http://stackoverflow.com/a/22030760/1370166 – TylerOhlsen May 07 '15 at 03:07
  • Hi, I tried using InjectionConstructor, Unity expects the decorator constructor arguments to be listed explicitly – garryp May 07 '15 at 09:28
  • 1
    The built-in `InjectionConstructor` does, but the custom `RequiredInjectionConstructor` defined in that answer does not. – TylerOhlsen May 07 '15 at 15:51
  • This works great. Does exactly what I needed it to do. – garryp May 08 '15 at 11:01

1 Answers1

1

In Ninject there is very useful functionality like this:

Bind<T>().To<T1>().WhenInjectedInto(typeof(T2));

It will initialize T2 with instance of T1 in constructor. Hope I understood you right. However, I am really interested if there's such thing in Unity, as it's also my primary IoC container.

mwilczynski
  • 3,062
  • 1
  • 17
  • 27
  • The question is giving the answer: use the InjectionConstructor. NInject syntax is cleaner, but the functionality is the same. http://stackoverflow.com/questions/5004306/how-to-conditionaly-bind-a-instance-depending-on-the-injected-type-using-unity – JotaBe May 07 '15 at 10:35
  • Ninject seems good when it works, but it seems extremely convoluted and poorly documented. Getting a Web API app up and running is a configuration nightmare. – garryp May 08 '15 at 08:38
  • I left Ninject behind because it's extremely slow. It is on the very, very bottom in any benchmark due to its performance. That's why I'm on Unity now, shame we don't have `WhenInjectedInto` right from the box... – mwilczynski May 08 '15 at 09:09