views:

150

answers:

2

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.

+2  A: 

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 :)

Jon Skeet
I think I might just have to take a IQueryProvider and IDataReader in the manager. The table manager is pretty much just a factory with a different name. I watched the google tech talk on DI with Miško Hevery and agree with what he says but I can never find any real world examples of the situation I'm in. It's all well and good to say "don't take objects just to pass them down" but without an example it means nothing. And I'm working on and SDK so every part needs to be stand alone.
Nathan W
Sorry about my bit of a rant. Thanks, at least I know I'm not the only one with this problem.
Nathan W
A: 

Could you add provider and reader as parameters on OpenTable()?

Who is calling OpenTable()? Does the caller know the provider and reader so that it can pass them to the method?

dss539