New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to use Ninject's Named bindings in Simple Injector? #389
Comments
Let me start by pointing out the problems with your design and how to fix those. After that I'll show how to make the configuration with your current design. You seem to be using one interface for two incompatible implementations. This is a Liskov Substitution Principle (LSP) violation. The LSP states that:
Or to translate to your case:
If both database have their own independent schema, the above statement will not hold and this implies you are violating LSP. It will fail, because your Violating LSP leads to applications that are more fragile and leads to DI configurations that are more difficult. In your case you even had to put library-specific attributes (i.e. Ninject's To solve this problem, and to adhere to the LSP, your interface should be split. For instance: public interface IMvSessionFactoryProvider { }
public interface IObaSessionFactoryProvider { } Each implementation can implement its own interface. This means you can simplify public TestDao(IMvSessionFactoryProvider sessionFactory) ... And registration can be done as follows: container.Register<IMvSessionFactoryProvider, MvSessionFactoryProvider>(Lifestyle.Singleton);
container.Register<IObaSessionFactoryProvider, ObaSessionFactoryProvider>(Lifestyle.Singleton); As you will see shortly, the above registrations are much simpler than any given alternative. This not only holds for Simple Injector, but as well for Ninject and any other DI Container. If however you are unable to improve the design of your application, you can still wire this up in Simple Injector, but I would strongly advise to take the time to improve the application's design, since that will save you in the long run. With the common warnings and preaches out of the way, let's take a look how to do this with Simple Injector: container.RegisterConditional<ISessionFactory, MvSessionFactoryProvider>(
Lifestyle.Singleton,
c => c.Consumer.Target.GetCustomAttribute<NamedAttribute>()?.Name == "MvSessionFactory");
container.RegisterConditional<ISessionFactory, ObaSessionFactoryProvider>(
Lifestyle.Singleton,
c => c.Consumer.Target.GetCustomAttribute<NamedAttribute>()?.Name == "ObaSessionFactory"); The previous registrations are condition, where the supplied predicate specifies the condition on which they apply. Here you see the registrations still depend on Ninject's These conditional registrations can be used in any way you want, so you can also remove the need to have attributes. This means however that there should be a different way to identify which consumer needs which dependency. Perhaps consumers live in a certain namespace: container.RegisterConditional<ISessionFactory, MvSessionFactoryProvider>(
Lifestyle.Singleton,
c => c.Consumer.ImplementationType.Namespace.EndsWith(".DataAccess.Mv"));
container.RegisterConditional<ISessionFactory, ObaSessionFactoryProvider>(
Lifestyle.Singleton,
c => c.Consumer.ImplementationType.Namespace.EndsWith(".DataAccess.Oba")); I hope this helps. |
Hello,
I'm migrating an application with NInject to Simple Injector. I use bind with names for some cases as more than one implementation of the same interface.
For example, this application has two databases and uses NHibernate. For each database I have a factory that builds the instance of every NHibernate session factory. For this I use the Named method of NInject:
Then I can perform the injection of each bind in the constructor, for example in a Dao:
I would like to know if there is something in the Simple Injector that allows me to work this way or if this approach is not ideal and there would be an ideal way to work with this type of situation.
Thanks
The text was updated successfully, but these errors were encountered: