Decorator Chains Resolution Question

Mar 13, 2008 at 11:44 PM
I am wanting to resolve dependencies across a chain with parameters.

ie.

Client-> ModelObject -> BusinessObject -> DataObject

client get's model from container

on the DataObjects constructor it takes a parameter, ie. ctor DataObject(string id)

When I get the ModelObject, how do I tell Unity to pass a value, ie. "1" to the DataObject construction in this chain ?

I don't want any references to DataObject in my Client, just ModelObject

End result:
Model.GetData() -> BusinessObject.GetData() -> DataObject.Execute() - uses that 'id' to retrieve the data

Mar 15, 2008 at 6:08 AM
You don't. At least not directly.

You could specify named dependencies, so that client depends on <ModelObject, "SpecificObject">, and that depends on <BusinessObject, "SpecificObject">, and that depends on <DataObject, "SpecificObject">. That one is configured to be constructed with a particular ID.

However, I would suggest that this is the wrong way to use a DI container. DI is best used to supply services, not domain entities. I would suggest that client should get a ModelObjectRepository injected. That repository knows how to figure out which model to hook up. The Model could also get a BusinessObjectRepository (or just have the code in it directly).

I'll have to cook up a bigger example, but I hope this gives you the gist of what I'm saying.

-Chris
Mar 15, 2008 at 1:18 PM
Thanks Chris.

I'm basing some of my idea on the following MSDN article:
http://msdn2.microsoft.com/en-us/library/aa973811.aspx

The only real difference between my particular setup and that article setup is that I have a data structure that needs to be provided several levels deep to the constructor of that object.

ie.
1 IRepository<Order>repository =
new ValidatingOrderRepository(
new SecurityRepository<Order>(
new LoggingRepository<Order>(
new CachingRepository<Order>(
new NHibernateRepository<Order>()))));
2 Order order = repository.Get(35);

I do have some state I'm passing through the layers.

My alternative is to goto the container at each step manually ?

I know that Windsor allows to pass a dictionary with a key, where that key would be matching that parameter

public DataObject(string id)...

When I create the model, this is passed along the chain?

pseudo code...
Hashtable ht = new Hashtable();
ht.Add("id", "35");
Model model = container<Model>.Get("Model1", ht);

When the container is resolving the dependencies and encounters a match of DataObject 'id' to the hashtable 'id' it would override the default id value with the value from the hashtable.

That would be what I would hope for here. Whether I use Repository, Dao, etc... I still need to have some values passed down to an underlying dependency.

Maybe I'm off in my thinking, but this is what I'm picturing - to me, this would be a great feature to have for Unity
Apr 8, 2008 at 5:36 PM
Below is an example of setting up a decorator chain. In my example, the IMyService that is injected into MyApplication is MyServiceImpl decorated by MyServiceDecorator

[Test]
public void MyServiceIsDecorated()
{
    MyApplication a = container.Resolve<MyApplication>();
 
    int result = a.Compute(2, 3);
 
    Assert.AreEqual(result, 10);
}

public class MyApplication
{
    private IMyService myService;
 
    public MyApplication(IMyService myService)
    {
        this.myService = myService;
    }
 
    public int Compute(int x, int y)
    {
        return myService.Compute(x, y);
    }
}

public interface IMyService
{
    int Compute(int x, int y);
}

public class MyServiceImpl : IMyService
{
    public int Compute(int x, int y)
    {
        return x + y;
    }
}

public class MyServiceDecorator : IMyService
{
    private IMyService myService;
 
    public MyServiceDecorator(IMyService myService)
    {
        this.myService = myService;
    }
 
    public int Compute(int x, int y)
    {
        return myService.Compute(x, y) * 2;
    }
}

<unity>
  <containers>
    <container>
      <types>
        <type
          name="MyServiceImpl"
          type="UnityConfigExample.IMyService, UnityConfigExample"
          mapTo="UnityConfigExample.MyServiceImpl, UnityConfigExample"/>
        <type
          type="UnityConfigExample.IMyService, UnityConfigExample"
          mapTo="UnityConfigExample.MyServiceDecorator, UnityConfigExample">
          <typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
            <constructor>
              <param name="myService" parameterType="UnityConfigExample.IMyService, UnityConfigExample">
                <dependency name="MyServiceImpl"/>
              </param>
            </constructor>
          </typeConfig>
        </type>
      </types>
    </container>
  </containers>
</unity>