views:

155

answers:

2

I'm building a blog engine to test some concepts such us TDD and using inversion of control... I came up with a setup where I'd have a generic IBlogRepository interface so I could support both SQL and XML.

public interface IBlogRepository : IRepository
{
 Post GetPostById(Guid postId);
 Post GetPostByFriendlyUrl(string friendlyUrl);

 List<Post> GetPostsByAuthor(string userName);  
 List<Post> GetPostByTags(params string[] tags);
 List<Author> Authors { get; }

 void Delete(Post post);
 void Delete(Comment comment);
 void Save(Post post);
 void Save(Comment comment);
}

The problem is the XML repository needs different resources than the database one does... here is the constructor:

 public XmlBlogRepository(string dataPath, IFileReader fileReader, IDirectoryReader directoryReader, ILogger logger)
 {
  this.dataPath = dataPath;
  this.fileReader = fileReader;
  this.directoryReader = directoryReader;
  this.Logger = logger;
 }

fileReader, directoryReader, and dataPath are not needed by the SQL Blog Repository.

This makes the issue of doing inversion of control to load the IBlogRepository impossible and it also makes it really hard to generically use them since they have completely different ctors.

The reason I have to pass them in is because if I just used File.Open/Directory.GetFiles then I wouldn't be able to unit test the class without having XML files on the hard drive.

+1  A: 

i think a provider will fit your needs by implementing a provider you will wrap the resources in it

here a nice link

Oscar Cabrero
This is basically what I've done, but since I wanted the class to be testable I had to pass the resources in as interfaces so that I could have mocked/fake objects take over the resources (File reader, data reader, etc.)
sontek
Provider Model is better than nothing, but otherwise an anti-pattern in light of many and better alternatives (namely IoC -- see Andrew Swan's answer)
chadmyers
+7  A: 

I don't understand why the fact that your two IBlogRepository implementations have different ctor signatures makes IoC "impossible"; on the contrary, this is a common scenario in IoC. The way it's addressed is that your IoC framework (and only your IoC framework) is responsible for calling the ctor of the desired IBlogRepository implementation. So your IoC configuration file (or whatever other config approach you use) knows which implementation is being used (something has to, after all), but the consumers of the IBlogRepository service only access it via its interface.

Andrew Swan
This is the right answer. The idea is to load up all your concrete implementations into the IoC config and then pull them out via abstractions (interface) for consumption. Satisfying the dependencies of SQL vs. XML now becomes a config-time excercise vs. runtime
chadmyers
I agree... there's nothing wrong with having different constructor signatures for different implementations. You just need to make sure your container knows how to create the dependencies for both.
John Price