How can I access the Ninject kernel from a separate c# project? - c#

I have a WCF application that uses Ninject (along with the NinjectWebCommon file) to take care of my dependency injection needs for the most part (this is done at app start); however, I have a separate project in the same solution that where I would like to use the kernel to resolve some dependencies at run-time. How can I get access to my kernel in this "other" project? Is it even possible?

How can I get access to my kernel in this "other" project?
You shouldn't do this. Only the startup path of your application should reference the container/kernel. This part is called the Composition Root. The kernel shouldn't be referenced outside the Composition Root; that would be an application of the Service Locator anti-pattern, and would cause all sorts of maintainability issues.
The 'trick' here is to define an abstract factory interface in your application. You can implement this factory inside your composition root. This will keep the kernel references only inside the composition root and will therefore not result in the Service Locator anti-pattern.
For instance:
// Defined in a core layer of the application
public interface IItemProcessorFactory {
IItemProcessor GetProcessor(ItemProcessorType type);
}
And inside your composition root (which could be a class or a namespace with multiple classes) you define an implementation:
// A nested type to exaggerate the fact that this is inside your Composition Root
private sealed class NinjectItemProcessorFactory : IItemProcessorFactory {
private readonly Kernel kernel;
public NinjectItemProcessorFactory(Kernel kernel) {
this.kernel = kernel;
}
public IItemProcessor GetProcessor(ItemProcessorType type) {
this.kernel.Get<IItemProcessor>(type.ToString());
}
}
And the factory can be registered as follows:
kernel.Bind<IItemProcessorFactory>().To<NinjectItemProcessorFactory>();

Related

Share Microsoft.Extensions.DependencyInjection.ServiceProvider configuration between projects

I have a solution that has the following projects
Acme.Core
Acme.Domain
Acme.Repositories
Acme.Services
Acme.Web
In the past I've used Unity for DI in full framework projects. I was able to register concrete objects to interface mappings in executable projects (web apps, console app, test apps).
I'm trying to implement the same approach with .NET Core. I wanted to first try using the Microsoft.Extensions.DependencyInjection library. Within the ASP.NET Core application it works great. Unfortunately I've run into an issue when I try to share/reference that instance with the registions to other projects, such as a .NET Standard library.
My idea was to inject the ServiceProvider into the constructor of the service:
public class AddressService : BaseService, IAddressService
{
private readonly IServiceProvider _serviceProvider;
public AddressService(IServiceProvider serviceProvider, string userOrProcessName)
{
_serviceProvider = serviceProvider;
}
public IReadOnlyList<IState> GetAllStates()
{
_serviceProvider.GetService<IAddressRepository>();
// other logic removed
}
}
I tried the following inside the Startup.ConfigureServices():
services.AddTransient<IAddressService>(s => new AddressService(HttpContext.RequestServices, Environment.UserName));
The issue I ran into is that I cannot reference HttpContext.RequestServices outside of a Controller. I haven't been able to figure another way of passing the ServiceProvider instance.
My questions:
How do pass a reference for the current ServiceProvider?
Is there a better design to accomplish my goal sharing the configuration of Microsoft.Extensions.DependencyInjection in multiple libraries?
Prevent injecting IServiceProvider into your application components; that leads to the Service Locator anti-pattern.
Instead, you should build up application components solely using Constructor Injection. This means that your AddressService should require IAddressRepository as constructor argument, not IServiceProvider. For instance:
public class AddressService : IAddressService
{
private readonly IAddressRepository repo;
public AddressService(IAddressRepository repo, IUserContext userContext)
{
this.repo = repo;
}
public IReadOnlyList<IState> GetAllStates()
{
// other logic removed
}
}
Also try to prevent injecting primites into your constructors. It's not a bad practice per se, but it does complicate object graph construction. Instead, either wrap the value into a class, in case its a configuration value, or hide it behind an abstraction (as shown above) in case it's a runtime value.
Both practices simplify both your application code and the Composition Root.
For instance, this will be the result of the previous AddressService redesign:
services.AddTransient<IAddressRepository, SqlAddressRepository>();
services.AddTransient<IAddressService, AddressService>();
services.AddScoped<IUserContext, UserContext>();
services.AddHttpContextAccessor();
Here, UserContext could be defined as follows:
public class UserContext : IUserContext
{
private readonly IHttpContextAccessor accessor;
public UserContext(IHttpContextAccessor accessor) => this.accessor = accessor;
public string UserName => this.accessor.HttpContext.User.Identity.Name;
}
In order to share configuration across multiple projects, you can put the configuration into a shared assembly, and register (not resolve) them in there. Many dependency injection libraries offer that functionality. e.g.
in Autofac you create a module (https://autofaccn.readthedocs.io/en/latest/configuration/modules.html) that takes a container builder to configure:
protected override void Load(ContainerBuilder builder) { ... }
SimpleInjector provides packages: https://simpleinjector.readthedocs.io/en/latest/howto.html#package-registrations
Unity can support something similar: Can I register my types in modules in Unity like I can in Autofac?
Ninject has a similar module feature: What is the intention of Ninject modules?
A similar feature has be created for Microsoft.Extensions.DependencyInjection: https://github.com/aruss/DotNetCore_ModularApplication
At a high level, you create a method that receives the DI container and adds your registrations to that container. If your DI framework doesn't provide hooks you need to manually call the method yourself, but the general concept doesn't change.
Splitting registrations into modules allows you to easily group similar sets of functionality while maintaining the flexibility of incorporating different sets of functionality into different projects. You could of course create a single shared assembly that registered the union of all dependencies for all projects, but that would carry around unnecessary baggage and result in a less reusable implementation.
The key point as Steven points out is that you configure the container and let it inject the dependencies rather than looking from the inside out for the dependencies.

Accessing unity container of web app from a class library

I have a class library for caching ( Redis ), we have a unity container inside this Redis class library
public class TCache<T>
{
static readonly IUnityContainer container = new UnityContainer();
private ITCache<T> ICacheStore;
static TCache()
{
container.RegisterType<ITCache<T>, TRedisCacheStore<T>>(new ContainerControlledLifetimeManager());
}
public TCache()
{
ICacheStore = container.Resolve<TRedisCacheStore<T>>();
}
Now my senior said me not use a separate container like this and I should be using the container which is already created inside the web app with the reason being that there should be only one single container.
My question is: is it possible to access a unity container that resides in a different project and is it necessary to do this change ?
Note: I cannot add the reference of the web app into the Redis cache class library.
You should only reference a container within your composition root (http://blog.ploeh.dk/2011/07/28/CompositionRoot/).
In other words, find where your current services are registered, and perform the generic registration there.
Your type that requires a cache store then takes your abstraction via constructor injection:
public class Cache<T>
{
private readonly ITCache<T> cacheStore;
public Cache(ITCache<T> cacheStore)
{
this.cacheStore = cacheStore
?? throw new ArgumentNullException(nameof(cacheStore));
}
}
By the way, using T as a prefix for your types (rather than as a prefix for generic type parameters) is very confusing.
The names TCache and ITCache are also very confusing.
Well, I share his view of the usage of the container. How I fixed this issue is (without going into the details of how I actually created it):
Make an option to register onto the container through an interface. Something like IRegisterContainer.Register(IUnityContainer container).
Then at the moment where you now register the mappings to the container, you extend that function to also search your assembly for all objects that implement that IRegisterContainer and make them register themselves.
And use this as a platform to fix your problem.
If you want to use the IUnityContainer in your TCache object to resolve the TRediscacheStore. Simply let the IUnityContainer register itself.
container.Register<IUnityContainer, container>().
And make it a dependency in the constructor of TCache.

Using Nininject MVC with class libraries

I'm quite new to IoC frameworks so please excuse the terminology.
So what I have is a MVC project with the Nininject MVC references.
I have other class libarys in my project e.g. Domain layer, I would like to be able to use the Ninject framework in there but all of my bindings are in the NinjectWebCommon.cs under the App_Start folder in the MVC project:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IHardwareService>().To<WindowsHardwareService>();
kernel.Bind<IStatusApi>().To<StatusApiController>();
}
Currently in my class library I am using constructor injection but sometime I am having to hardcode the dependencies:
var service = new WindowsHardwareService();
When I would like to be able to do the following:
IKernel kernel = new StandardKernel(.....);
var context = kernel.Get<IHardwareService>();
I have not been doing the following because I do not have any modules?
All of the documentation I have read is mainly aimed at the regular Ninject library and not the MVC version.
What do I need to do, and how can I use the regular Ninject library with the MVC version?
Update
This is what I have tried:
The aim of this is so that each project can load the module and get the current injected interface.
App_Start/NinjectWebCommon.cs (In MVC Project)
private static void RegisterServices(IKernel kernel)
{
var modules = new IoCModules();
var newKernal = modules.GetKernel();
kernel = newKernal;
}
IoCModules.cs (In Project.Ioc project)
public class IoCModules
{
public IKernel GetKernel()
{
var modules = new CoreModule();
return modules.Kernel;
}
}
CoreModule.cs (In Project.IoC.Modules project) <-- This is where all the references to all projects are, this get's around any circular dependency issues.
public class CoreModule : NinjectModule
{
public override void Load()
{
Bind<IHardwareService>().To<WindowsHardwareService>();
Bind<IStatusApi>().To<StatusApiController>();
}
}
But I am currently getting the following:
Error activating IHardwareService
No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IHardwareService into parameter service of constructor of type DashboardController
1) Request for DashboardController
Suggestions:
1) Ensure that you have defined a binding for IHardwareService.
2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
3) Ensure you have not accidentally created more than one kernel.
4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
5) If you are using automatic module loading, ensure the search path and filters are correct.
It seems that you have a lot of questions what needs to be answered here, so I will try to do my best.
Based on your current question I will try to "draw up" a simplified architecture of your current implementation:
Domain layer: The core of your domain, place of your business entities, etc.
Infrastructure layer: This is where your services reside e.g.: WindowsHardwareService
IOC: I tend to call to this as DependencyResolution assembly.
UI: MVC application
Assuming this all above, we can state that your applications Composition Root or Entry point is the UI MVC project. One of the main concepts using a DI Container that is you initalize it in the Composition Root set up/do all your needed bindings and registrations here. The main intention to do it in the entry point is to avoid the Service Locator anti-pattern.
By using a DI Container you don't new() up your class implementations or get the kernel but rather ask for the registered dependency, following the rule of Inversion Of Control or also known as the Hollywood principle.
After the philosphy course, we can finally get to some actual implementation.
Creating an Ninject module: in your IOC assembly, lets call this file as ServiceModule.cs
using Ninject.Modules;
public class ServiceModule : NinjectModule
{
public override void Load()
{
Bind<IHardwareService>().To<WindowsHardwareService>();
Bind<IStatusApi>().To<StatusApiController>();
}
}
This will be the Ninject module that you will register/load in the Composition Root.
Now about the Composition Root: in UI MVC projects NinjectWebCommon.cs
You can have a method that is responsible loading your modules as below.
private static void RegisterServices(IKernel kernel)
{
var modules = new List<INinjectModule>
{
new ServiceModule()
//, new FooModule()
//, new BarModule()
};
kernel.Load(modules);
}
And finally your DashboardController in UI MVC:
public class DashboardController : Controller
{
private readonly IHardwareService _hardwareService;
public DashboardController(IHardwareService hardwareService)
{
_hardwareService = hardwareService;
}
}
At this point, your ask for the registered implementation of IHardwareService in the controllers constructor. The DI Container will do the dirty job and pass you the instance that you can work with later in your controller.
A note about the interfaces: I tend to put these into an own assembly, where I just store the interfaces, e.g.: Project.Domain.Interfaces or Project.Infrastructure.Interfaces where each of these assemblies contain only domain or infrastructure interfaces.
References between assemblies:
To put all these together the UI only references the IOC assembly and the interfaces assembly that containts the interfaces you bound in your Ninject Module.
Summarizing all of the above:
Your classes and interfaces alone by theirselves are just pieces what are getting glued together by the DI container.
Hope I cleared it up a bit.
EDIT: as some good advice that #AndreySarafanov pointed out in comments, if you need different implementations of an interface you ask for in the constructor, you can use a Ninject Factory. For more information you can refer to this answer.

Using NinjectModules from Service layer

I fail to understand how to probably setup my Ninject IoC container.
I have a Service layer which contains implementations of several services and implementation of my DbContext and ASP.NET Identity like so:
public class IdentityModule : NinjectModule
{
public override void Load()
{
Bind<IUserStore<User, int>>().To<UserService>().InSingletonScope();
Bind<UserManager<User, int>>().ToSelf().InSingletonScope();
Bind<IRoleStore<UserRole, int>>().To<UserRoleService>().InSingletonScope();
Bind<RoleManager<UserRole, int>>().ToSelf().InSingletonScope();
}
}
public class EntityFrameworkModule : NinjectModule
{
public override void Load()
{
Bind<EntityDbContext>().ToSelf();
Bind<ICreateDbModel>().To<DefaultDbModelCreator>();
Bind<IUnitOfWork>().To<EntityDbContext>();
Bind<IWriteEntities>().To<EntityDbContext>();
Bind<IReadEntities>().To<EntityDbContext>();
}
}
These are loaded into my NinjectWebCommen (MVC layer):
private static void RegisterServices(IKernel kernel)
{
var modules = new INinjectModule[]
{
new EntityFrameworkModule(),
new IdentityModule()
};
kernel.Load(modules);
}
Now my question is:
My EntityDbContext should be request scoped, but I am unable to set .InRequestScope() from my service layer. Should this INinjectModule then be moved to the MVC layer instead of lying in the service layer or should I reference Ninject.Web.Common in my service layer? This just seem to be a wrong way since the service layer is not a web-app.
This place where you wire everything together is called the
Composition Root in DI terminology
One of the suggestions is to create a bootstrap for all layers. Check this SO:
Where to locate Ninject modules in a multi-tier application
This is not the best answer but I have been having the same problem. First, make sure Ninject and Ninject.Web.Common are referenced in the service layer, and that you have a using statement for Ninject.Web.Common in your module class.
I couldn't find InRequestScope in Intellisense. I tried a few times opening and closing the project, and it finally showed up. Didn't do anything but close and re-open Visual Studio and it started working.

how to implement IOC without a global static service (non-service locator solution)?

we want to use Unity for IOC.
All i've seen is the implementation that there is one global static service (let's call it the the IOCService) which holds a reference to the Unity container, which registers all interface/class combinations and every class asks that object: give me an implementation for Ithis or IThat.
Frequently i see a response that this pattern is not good because it leads to a dependency from ALL classes to the IOCService (not to the Unity container because it is only known inside the IOCService).
But what i don't see often, is: what is the alternative way?
Michel
EDIT: found out that the global static service is called the service locator, added that to the title.
The alternative is to have a single instance of your container at the highest application level only, then use that container to resolve every object instance you need to create in that layer.
For example, the main method of most executables just looks like this (minus exception handling):
private static void main(string[] args) {
Container container = new Container();
// Configure the container - by hand or via file
IProgramLogic logic = container.Resolve<IProgramLogic>();
logic.Run();
}
Your program (represented here by the IProgramLogic instance) doesn't have to know anything about your container, because container.Resolve will create all its dependencies - and its dependencies' dependencies, on down to leaf classes with no dependencies of their own.
ASP.NET is a harder case, because web forms doesn't support constructor injection. I typically use Model-View-Presenter in my web forms applications, so my Page classes really only have one dependency each - on their presenter. I don't unit test them (everything interesting and testable is in my presenters, which I do test), and I don't ever substitute presenters. So I don't fight the framework - I just expose a container property on my HttpApplication class (in global.asax.cs) and use it directly from my Page files:
protected void Page_Load(object sender, EventArgs args) {
ICustomerPresenter presenter = Global.Container.Resolve<ICustomerPresenter>();
presenter.Load();
}
That's service locator of course - though the Page classes are the only thing coupled to the locator: your presenter and all of its dependencies are still fully decoupled from your IoC container implementation.
If you have a lot of dependencies in your Page files (that is, if you do not use Model-View-Presenter), or if it's important to you to decouple your Page classes from your Global application class, you should try to find a framework that integrates into the web forms request pipeline and use property injection (as suggested by Nicholas in the comments below) - or write your own IHttpModule and perform the property injection yourself.
+1 for knowing that Service Locator is a Bad Thing.
Problem is - Unity is not very sophisticated so I don't know how easy/hard is it to do IoC the right way with it.
I wrote few blogposts recently that you might find useful.
How I use IoC Containers
Pulling from the container
Instead of using the container explicitly, use it implicitly by leveraging constructor / property injection instead. Create a core class (or set of core classes) that depend on all the major pieces of your application.
Most containers will let you put ISomething[] in your constructor and it will inject all instances of ISomething into your class.
This way, when you bootstrap your application:
Instantiate your container
Register all your goodies
Resolve the core classes (this will pull in all the other dependencies you need)
Run the "main" part of the application
Now, depending on the type of application you are writing, there are different strategies for avoiding marking the IoC container as "static".
For ASP.NET web applications, you'll probably end up storing the container in the Application State. For ASP.NET MVC applications, you need to change out the Controller Factory.
For desktop applications, things get more complicated. Caliburn uses an interesting solution to this problem using the IResult construct (this is for WPF applications but could be adapted for Windows Forms as well.
In theory, to not have to worry about having a static IoC instance, you need to follow the Fight Club Rule - i.e. not to talk about the fight club - i.e. not to mention the IoC container.
This means that your components should largely be unaware about the IoC container. It should only be used at the topmost level when registering components. If a class needs to resolve something, it should really be injected as a dependency.
The trivial case is easy enough. If PaymentService depends on IAccount, the latter should be injected by IoC:
interface IAccount {
Deposit(int amount);
}
interface CreditCardAccount : IAccount {
void Deposit(int amount) {/*implementation*/}
int CheckBalance() {/*implementation*/}
}
class PaymentService {
IAccount account;
public PaymentService (IAccount account) {
this.account = account;
}
public void ProcessPayment() {
account.Deposit(5);
}
}
//Registration looks something like this
container.RegisterType<IAccount, CreditCardAccount>();
container.RegisterType<PaymentService>();
The not so trivial case is where you want to inject multiple registrations. This especialy applies when you are doing any sort of Converntion Over Configuration and creating an object from a name.
For our payment example, say you want to enumerate through all accounts and check their balances:
class PaymentService {
IEnumerable<IAccount> accounts;
public PaymentService (IEnumerable<IAccount> accounts) {
this.accounts = accounts;
}
public void ProcessPayment() {
foreach(var account in accounts) {
account.Chackbalance();
}
}
}
Unity has the ability to register multiple interface to class mappings (they have to have different names thought). It does not, however, automatically inject those into classes that take collections of those registered interfaces. So, the above example will throw a resolution failed exception at runtime.
If you don't care that those objects live forever, you can register PaymentService in a more static fashion:
container.RegisterType<PaymentService>(new InjectionConstructor(container.ResolveAll<IAccount>()));
The above code will register PaymentService and will use a collection of IAccount instances that is resolved at registration time.
Alternatively, you can pass an instance of the container itself as a dependency and let PaymentService perform resolution of accounts. This is not quite following the Fight Club Rule, but is slightly less smelly than static Service Locator.
class PaymentService {
IEnumerable<IAccount> accounts;
public PaymentService (IUnityContainer container) {
this.accounts = container.ResolveAll<IAccount>();
}
public void ProcessPayment() {
foreach(var account in accounts) {
account.Chackbalance();
}
}
}
//Registration is pretty clean in this case
container.RegisterType<IAccount, CreditCardAccount>();
container.RegisterType<PaymentService>();
container.RegisterInstance<IUnityContainer>(container);
If your concern is having a dependency on Unity throughout your application, you can combine the service locator with a facade to hide the IOC implementation. In this way, you do not create a dependency on Unity in your application, only on having something that can resolve types for you.
For example:
public interface IContainer
{
void Register<TAbstraction,TImplementation>();
void RegisterThis<T>(T instance);
T Get<T>();
}
public static class Container
{
static readonly IContainer container;
public static InitializeWith(IContainer containerImplementation)
{
container = containerImplementation;
}
public static void Register<TAbstraction, TImplementation>()
{
container.Register<TAbstraction, TImplementation>();
}
public static void RegisterThis<T>(T instance)
{
container.RegisterThis<T>(instance);
}
public static T Get<T>()
{
return container.Get<T>();
}
}
Now all you need is an IContainer implementation for your IOC container of choice.
public class UnityContainerImplementation : IContainer
{
IUnityContainer container;
public UnityContainerImplementation(IUnityContainer container)
{
this.container = container;
}
public void Register<TAbstraction, TImplementation>()
{
container.Register<TAbstraction, TImplementation>();
}
public void RegisterThis<T>(T instance)
{
container.RegisterInstance<T>(instance);
}
public T Get<T>()
{
return container.Resolve<T>();
}
}
Now you have a service locator that is a facade for IOC services, and can configure your service locator to use Unity or any other IOC container. The rest of the application has no dependency on the IOC implementation.
To configure your service locator:
IUnityContainer unityContainer = new UnityContainer();
UnityContainerImplementation containerImpl = new UnityContainerImplementation(unityContainer);
Container.InitializeWith(containerImpl);
For testing, you can create a stub of IContainer that returns whatever you want, and initialize Container with that.

Categories