1

I have an interface IRepository and an implementation EFRepository.
I use structuremap injection in order to get the repository implementation.
Right now the EFRepository has constructor with no parameter so structuremap knows to retrieve instances on EFRepository easily.

Now I need to change the repository implementation so that it will recieve in the constructor parameter that holds the unit of work.

My question in such case, how I use structuremap in order to return an instance that initialized with the unit of work?

EXAMPLE
Until today I used:

using(IUnitOfWork uow=UnitOfWork.current) {
    IRepository rep = ObjectFactory.GetInstance<IRepository<T>>();
    //repository operations that uses UnitOfWork.current that initialized above
}// here dispose of UnitOfWork.current

Now I want to use:

using(IUnitOfWork uow=new UnitOfWork()) {
    //Not sure is this is how I tell sructure map to use contractor that 
    //get IUnitOfWork)    
    IRepository rep = ObjectFactory.GetInstance<IRepository<T>>(uow);
    //repository operations that uses uow that initialized above
}// here dispose of UnitOfWork
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Naor
  • 23,465
  • 48
  • 152
  • 268
  • Just to clarify, are you saying that you want to add a parameter to your constructor and you want to make sure that StructureMap can inject the appropriate dependency? – csano May 17 '11 at 06:45

2 Answers2

2

I'm assuming here that your unit of work is request-specific... So you have a service (WCF?) and each incoming request gets its own unit of work.

Then you can configure StructureMap to define a separate unit of work per HTTP Request. If you need unit testing without HTTP Requests, you can choose for a hybrid lifecycle: per HTTP Request OR per thread. StructureMap will figure out what to do at runtime.

ObjectFactory.Configure(x => x.For<IUnitOfWork>()
              .HybridHttpOrThreadLocalScoped()
              .Use<MyUnitOfWork>());

Your class that needs the constructor injection simply states that it needs an IUnitOfWork:

public MyClass(IUnitOfWork unit) { ... }

This of course requires that MyClass is also managed/instantiated using StructureMap.

Roy Dictus
  • 32,551
  • 8
  • 60
  • 76
  • @Roy Dictus: But if structuremap wil create the unitofwork for my, I won't need using statement and this way I will not be able to dispose the unit of work.. Can you put example of how using the unit of work and the repository in your solution? – Naor May 17 '11 at 07:01
  • If your unit of work needs to be disposed -- that is, if it holds unmanaged resources -- you will need to implement the IDisposable interface on it. StructureMap will then properly dispose of your object when it is no longer needed. – Roy Dictus May 17 '11 at 07:15
  • @Roy Dictus: my UnitOfWork implements IDisposable. Are you sure that StructureMap will dispose it automatically? – Naor May 17 '11 at 07:20
  • @Roy Dictus: here they say that structuremap will not dispose automatically: http://stackoverflow.com/questions/5015354/structuremap-disposing-of-datacontext-object – Naor May 17 '11 at 07:21
  • That is a different story. In the discussion you mention, an explicit instance is created using the Service Locator / Object Factory. That is not the same as constructor injection. With constructor injection, the IOC container (StructureMap in this case) is the one creating the instance. – Roy Dictus May 17 '11 at 07:36
  • StructureMap will not dispose the transient objects it create unless you are using a nested container. – PHeiberg May 17 '11 at 09:27
  • @PHeiberg: Not even if they are HybridHttpOrThreadLocalScoped? – Roy Dictus May 17 '11 at 11:06
  • @Roy Dictus - No, not even then. The container is not designed to control the disposal of objects. You need to implement some kind of mechanism for doing it. A common way is to hook into the BeginRequest/EndRequest in the HttpHandler and perform the creation/disposal there, either by fetching the object from the container and disposing it or creating a nested container and disposing it. – PHeiberg May 17 '11 at 11:18
  • @PHeiberg: Thanks, I stand corrected. Interesting stuff. I found some info on the nested containers at http://codebetter.com/jeremymiller/2010/02/10/nested-containers-in-structuremap-2-6-1/. I was convinced StructureMap handles this itself. Apparently it's Autofac that can do it automagically: http://code.google.com/p/autofac/wiki/DeterministicDisposal – Roy Dictus May 17 '11 at 11:29
  • @PHeiberg: Do you have any recommendation? – Naor May 17 '11 at 19:34
  • @Naor: I'd go with Roy's recommendation, but add a nested container and make sure to dispose it in an EndRequest event handler. See Roy's previous comment about nested containers and Jeremy's reply to this question: http://groups.google.com/group/structuremap-users/browse_thread/thread/6be80baf98c25820 – PHeiberg May 17 '11 at 20:31
1

In order to pass a specific instance to ObjectFactory you can use "with":

IRepository rep = ObjectFactory.With<UnitOfWork>(uow).
  GetInstance<IRepository<T>>();
PHeiberg
  • 29,411
  • 6
  • 59
  • 81
  • I gave this a vote for being correct and answering the exact question asked. However, I think the guidance in the Roy Dictus answer is a better approach (though it needs to mention nested containers for proper disposal). – Joshua Flanagan May 17 '11 at 12:55
  • @Joshua - I agree, Roy's answer is better from an architectural standpoint and the right way to go in order to create a logical and maintainable solution – PHeiberg May 17 '11 at 15:22