Injection different implementation due to where dependend class is used

Nov 18, 2009 at 5:05 AM

Hi,

Can somebody advice me how can I implement following injection.

I've got two versions of hibernate sessions. The first have per http request liftime and the second per wcf call life time:

this.Container.RegisterType<ISession>("MVCSession", new PerRequestLifeTimeManager(), new InjectionFactory(c => c.Resolve<ISessionFactory>().OpenSession()));

this.Container.RegisterType<ISession>("WCFSession", new PerWCFCallLifeTimeManager(), new InjectionFactory(c => c.Resolve<ISessionFactory>().OpenSession()));

And I've got a Repository class which depends of ISession

I want MVCSession to be injected in repository if it is used in MVC Controller and WCFSession if repository is used inside WCF service implementation.

Or this is overuse of DI container and I should change my approach?

Best regards,

Alexey Zakharov.

Nov 18, 2009 at 5:31 AM
Edited Nov 18, 2009 at 5:32 AM

Currenlty I'm using following approach, but i have a feeling that made something wrong.

Container.RegisterType<IMVCRepository, Repository>(new InjectionConstructor(new ResolvedParameter<ISession>("MVCSession")));

Container.RegisterType<IWCFRepository, Repository>(new InjectionConstructor(new ResolvedParameter<ISession>("WCFSession")));

 

Nov 18, 2009 at 6:00 AM

That's a perfectly reasonable way to do it.

The other option I can think of off the top of my head is to use two containers - or maybe three. One root container, then two child containers, one for the MVC specific stuff and one for the WCF specific stuff. Either will work.

 

Nov 18, 2009 at 6:31 AM

That is nice approach, but how it would work if I have to deal with IServiceLocator?

Nov 18, 2009 at 6:36 AM

Both WCF and MVC controllers factories uses ServiceLocator to resolve instances.

Nov 18, 2009 at 6:41 AM

Looks strange, but.. : ServiceLocator.Current.GetInstance<IServiceLocator>("MVC").GetInstance<IFooController> =))))

 

Nov 20, 2009 at 3:28 AM

How do the MVC and WCF factories get their service locator to begin with? Can you construct them with different ones?

 

 

Nov 20, 2009 at 4:28 PM

Currently I'm using ServiceLocator.Current. And as I know it is not possible to inject it there other way.

As I said in previous comment. I can get named instances of IServiceLocator. But it looks strange. Don't you think so?

Nov 25, 2009 at 9:30 AM

I solved the problem using childcontainer:

            this.Container.RegisterType<IRepository, Repository>(new ContainerControlledLifetimeManager());
            IUnityContainer wcfContainer = this.Container.CreateChildContainer();

            wcfContainer.RegisterType<ObjectContext>(
                new WcfPerCallLifeTimeManager(),
                new InjectionFactory(c => { return new ObjectContext(@"name = ModelContainer"); }));

            var contextStorage = new ContextStorage(() => wcfContainer.Resolve<ObjectContext>());

            wcfContainer.RegisterInstance<IContextStorage>(contextStorage);

            this.Container.RegisterType<ILibrariesService, LibrariesService>
                (
                new InjectionConstructor(
                    wcfContainer.Resolve<IRepository>(),
                    this.Container.Resolve<IFileSystemRepository>())
                );

Dec 12, 2009 at 10:42 AM

Finally we chose following approach:

ServiceLocator.Current.GetInstance<IServiceLocator>("MVC").GetInstance<IFooController>

So we get specific locator which uses child container as dependency provider.

Do you think it is good approach?