Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DI object graph building - separating logic and construction graph

Sorry if this is a really basic question but it's been really getting to me. I really like the idea of DI, it really helps me with my testing but I have hit a bit of a brick wall I think. So I have two types:

 Table
 TableManager

Now the table object has a constructor on it like this:

Table(ITableCommandRunner tableRunner,
      IQueryProvider queryProvider,
      IDataReader reader,
      string Name)

Now the table object pretty much only uses those objects so following the rule that you ask for what you need I pass them in. Now my TableManager object is used to Open and Close etc tables. The only thing it needs is a ITableCommandRunner so I pass that in the constructor.

 TableManager(ITableCommandRunner tablrunner)

Ok that's fine but in the TableManager.OpenTable command I need call the open table commmand on the ITableCommandRunner and then construct a new Table object to pass back.

    public ITable OpenTable(string tableName) 
    {
        // Call open table command on tablerunner.
        // I need a IQueryProvider and IDataReader to pass to the table.
        return new Table<TEntity>(this.tablerunner, provider,reader, tableName);
    }

but now in my open table command I have to make a IDataReader and IQueryProvider. If I pass them into the constructor of TableManager doesn't that violate "taking objects just to pass it down to a inner type and not really using them".

I'm not really sure how I do this. Could anyone help me with this?

I'm just not sure how I separate object construction and logic.

like image 888
Nathan W Avatar asked Jul 05 '09 07:07

Nathan W


1 Answers

One option is to configure a TableFactory which does know the query provider and reader, and only needs to know the table name. You can then pass the factory to the TableManager. On the other hand, a TableManager sounds like it probably needs to be the factory itself - in which case it simple does need the provider and reader, even though it may not be obvious to start with, given that it's just passing them along.

I agree it gets a bit messy - basically if something "deep in the tree" (and dynamically created) requires a piece of information, then anything creating it needs that information - and anything creating that creator needs it, etc. It can certainly become a mess if you're not careful (and sometimes even if you are).

Depending on your DI framework, you may be able to configure a factory-like object in the container and then ask that to create a new instance at execution time. That means your code becomes coupled with the DI framework of course - it's a case of swings and roundabouts. Basically the information has to be somewhere and you'll always need to have some "reference chain" to get to it when you need it.

Sorry not to have a cheerier outlook on it, but even if these ideas don't help you very much at least you know you're not alone :)

like image 95
Jon Skeet Avatar answered Oct 18 '22 09:10

Jon Skeet