views:

483

answers:

2

I've implemented a repository pattern with persistence ignorance. The repository implementation only interacts with my entity objects, IUnitOfWork and ITable<T> interfaces. The intention is that the IUnitOfWork isn't reused but represents a single transaction. So far, I've implemented in-memory as well as Linq-to-Sql versions of the IUnitOfWork and ITable<T>.

My problem is that due to the IUnitOfWork injection into the repository, I end up with needing to know how to instantiate a new IUnitOfWork where ever the repository is used. Since this is the primary piece that is supposed to be pluggable it feels like I've done something wrong. The general usage pattern is something like this:

FooUnitOfWork unitOfWork = new FooUnitOfWork();
Repository repos = new Repository(unitOfWork);
// ...act upon repos
unitOfWork.Save();

Now it appears that I need some other pattern to allow every repository usage in the app to obtain the correct unit of work (e.g. in-memory, L2S, etc.).

What is the most fitting pattern for this? I've looked at Fowler's discussion on the topic but none of his examples seem to be a clean fit. I already feel like the amount of abstraction that I have is more than I'd like so building yet another indirection seems excessive.

At the moment, I'm leaning toward some sort of app-wide provider which can be configured to produce the correct IUnitOfWork. Am I off-base or is this what is needed to truly be implementation agnostic?

A: 

I would suggest using a Vistor pattern to discover the implementations of the IUnitOfWork interface.

[UnitOfWork(Name="foo")]
public class FooUnitOfWork : IUnitOfWork {}

Repository repo = new Repository("foo");
//stuff happens
repo.Save(); //or repo.Worker.Save();

Inside the repo instance a discovery factory finds the worker and creates it.

Joe Caffeine
I'm not seeing how that makes it easier to determine *which* `IUnitOfWork` implementation I want. The code that uses it will be the same for all implementations, otherwise I'd just instantiate the `IUnitOfWork` I want.
McKAMEY
Using an attribute(s) and a runtime locator like visitor, you can mark up the implementations with metadata that allow your factory to choose the best fit.
Joe Caffeine
There is nothing for it to switch off of. Every instantiation in the logic is exactly the same (e.g. your example without passing in "foo") because it is at a app-wide configuration level that the storage mechanism is chosen. It's much more analogous to the ASP.NET Provider model.
McKAMEY
Sounds like you answered your own question...app-wide configuration suggests keeping the switch in a config file. You can extend the system.configuration classes if you want something more than a simple string key. This is how the asp.net providers and wcf channels get selected.
Joe Caffeine
A: 

Update: while this didn't really break down it ended up just producing a poor-man's IoC Container. I ended up just replacing all of these:

UnitOfWorkFactory.Create();

with the generalized Common Service Locator implementation:

Microsoft.Practices.ServiceLocation.ServiceLocator.Current.GetInstance<IUnitOfWork>();

This allowed me to create a library which uses Dependency Injection without forcing all users to use the same IoC framework.


Perhaps I should use a very simple factory where I can set a callback? It could have a set of static methods on it like this:

public static class UnitOfWorkFactory
{
 private static Func<IUnitOfWork> FactoryMethod;

 public static IUnitOfWork Create()
 {
  if (UnitOfWorkFactory.FactoryMethod == null)
  {
   throw new InvalidOperationException("...");
  }

  return UnitOfWorkFactory.FactoryMethod();
 }

 public static void SetFactoryMethod(Func<IUnitOfWork> factory)
 {
  UnitOfWorkFactory.FactoryMethod = factory;
 }
}

Where does this break down?

McKAMEY
Since there hasn't been a better solution I guess I'm rolling with this. I would still be interested in hearing where this breaks down or if someone has another perspective.
McKAMEY