I'm in the process of converting my application from Ninject to Simpler Injector. I am trying to pass a constructor argument (in this case NHibernate session) into the container via getInstance(). In ninject, this was accomplished by using following:
return _kernel.Get<IRepository<T>>(new ConstructorArgument("mysession", GetMySession()));
How can I accomplish this with Simple Injector? I have HibernateFactory class where binding is done with repository:
public class NHSessionFactory : IMySessionFactory
{
private readonly ISessionFactory myNHSessionFactory;
public NHSessionFactory(Assembly[] myMappings){
this.myNHSessionFactory = InitNHibernate(myMappings);
MyLocator.MyKernel.Bind(typeof(IRepository<>)).To(typeof(NHRepository<>));
}
public IMySession CreateSession()
{
return new NHSession(this.myNHSessionFactory.OpenSession());
}
....
The MyLocator class has following:
public class MyLocator
{
private static StandardKernel kernel;
private static ISessionFactory sessionFactory;
static MyLocator()
{
this.kernel = new StandardKernel();
this.kernel.Load(new DependencyInjector());
}
public static StandardKernel MyKernel
{
get
{
return this.kernel;
}
}
public static ISession GetMySession()
{
....
return this.kernel.Get<ISession>();
}
.....
public static IRepository<T> GetRepository<T>() where T : MyEntity
{
return this.kernel.Get<IRepository<T>>(new ConstructorArgument("mysession", GetMySession()));
}
Please let me know how I can achieve this with Simple Injector. I have read that Simple Injector does not allow out of box support for passing runtime values through retrieval methods (i.e. getInstance). What are the alternatives? Are there options with Registration (RegisterConditional) and if so, how?
There is no out-of-the-box support for passing on runtime values onto the GetInstance
method to complete the auto-wiring process. This is because it is typically a sign of suboptimal design. There are ways around this, but in general I advice against doing this.
In your case, even in your current design, it seems completely unnecessary to pass on the session as runtime value during object construction (even with the use of Ninject). If you just register the ISession
in the container, you can let Simple Injector (or Ninject) auto-wire it for you, without having to pass it as runtime value. This might even remove the need to have this IMySessionFactory
abstraction and implementation.
Your code might start to look like this:
Assembly[] myMappings = ...
ISessionFactory myNHSessionFactory = InitNHibernate(myMappings);
container.Register<IMySession>(myNHSessionFactory.OpenSession, Lifestyle.Scoped);
container.Register(typeof(IRepository<>), typeof(NHRepository<>));
With this configuration you can now resolve a repository using container.GetInstance<IRepository<SomeEntity>>()
or use IRepository<T>
as constructor argument.