views:

163

answers:

2

Using the adapter pattern, combined with IoC (specificly Unity), I would like to create a new instance of a object of which the properties point back to the adaptee's propeties (basicly mapping the adaptee to a target object).

As a example I have the following class structures:

public class Adaptee
{
    private Adaptee() { }

    public int MyProperty { get; set; }

    public static Adaptee New()
    {
        return new Adaptee();
    }
}

public class Target
{
    public int MyProperty { get; set; }
}

public class Adapter : Target
{
    public Adapter(Adaptee adaptee)
    {
        this.MyProperty = adaptee.MyProperty;
    }
}

public class MyTestClass
{
    public Target MyTarget { get; set; }
}

The problem is that the Adaptee is not under my control and it has no public constructor, hence the use of the adapter. So Adaptee gets created as follow

Adaptee adaptee = Adaptee.New();
adaptee.MyProperty = 5;

In the actual code the above code would be executed in a externally controlled assembly and then passed to the following code:

using (UnityContainer container = new UnityContainer())
{
    container
        .RegisterType<MyTestClass>(
            new InjectionProperty("MyTarget"));

    container.RegisterInstance<Adaptee>(adaptee, new ExternallyControlledLifetimeManager());

    MyTestClass myTestClass = container.Resolve<MyTestClass>();
}

I would like the execution of the code to result in the following:

Debug.Assert(myTestClass != null);
Debug.Assert(myTestClass.MyTarget != null);
Debug.Assert(myTestClass.MyTarget.MyProperty == adaptee.MyProperty);

This means that a resolved instance of Adapter should be injected into the MyTarget property of the myTestClass instance. The instance of Adapter should have been created with externally created instance of Adaptee.

The following code:

container
    .RegisterType<MyTestClass>(
        new InjectionProperty("MyTarget"));

should actually result in this:

container
    .RegisterType<MyTestClass>(
        new InjectionProperty("MyTarget", container.Resolve<Adapter>()));

This does not seem to be possible, since no instance of Adapter exist yet and it has a private constructor.

Should I use interception or something to achive this?

A: 

That was a Doh! moment.

The solution is to add the following when configuring unity:

.RegisterType<Target, Adapter>()

I can't believe I missed that, such a simple solution which solves the problem (I think).

So te MyTarget property on the MyTestClass will resolve to a instance of the Adapter since it inherits from Target. The Adapter will obviously be initiated with the externally created instance of the Adaptee class.

Schalk
So it's a double Doh! moment.The above code works, but it is not necessarily ideal. The Target type should not always resolve to the Adapter type, in this case it should only resolve to Adapter when injection happens for the MyTarget property in MyTestClass.
Schalk
A: 

I was close with the container.Resolve<Adapter>() idea, but the final answer is simply to use the ResolvedParameter class when configuring the property to be injected using the InjectionProperty class:

new InjectionProperty(
  "MyTarget", 
  new ResolvedParameter<Adapter>()));

So the calling code would look as follow:

Adaptee adaptee = Adaptee.New();
adaptee.MyProperty = 5;

using (UnityContainer container = new UnityContainer())
{
    container
        .RegisterType<MyTestClass>(
            new InjectionProperty(
              "MyTarget",
              new ResolvedParameter<Adapter>()));

    container.RegisterInstance<Adaptee>(adaptee, new ExternallyControlledLifetimeManager());

    MyTestClass myTestClass = container.Resolve<MyTestClass>();
}

I found the solution in the following post: Setter / property injection in Unity without attributes

Hope this helps someboby else.

Schalk