I understand DI and IoC but I can't seem to understand how to implement it in a nTier application. This is a simple MVC application I'm trying to build with one domain object.
Layers: DAL and UI will reference the BLL Layer.
DAL<--BLL-->UI
DAL will contain EntityFramework, SQLBlogRepository, Blog.cs and Mapper
BAL will contain IBlogRepository, Domain object: Blog.cs
UI will implement Constructor DI of IBlogRepository
This is where I'm stuck. How can I used Ninject so the constructor know to used SqlBlogRepository implementation? I also ran into a few examples that uses "Composition Root" which add more confusion. Then there are example that uses Repository Pattern. The bottom line is, I'm trying implement a nTier MVC application that is loosely couple and used IoC/Dependency Injection. Please help me map out how I can make a call from the UI layer and have the DAL layer return data via BLL layer while all three layer are loosely coupled.
I am assuming you do not have a ninject configuration file created. So here is how we did it where I am at.
To explain what I am doing. You need to have your concrete class implement whatever Interface you want to use.
In the ninject config file you need to bind your Interfaces to your concrete classes. Then you can call ninject to get your interfaces and it will return the concrete class that you want.
If you want to use this in an N- Tier development environment.
DAL <- >BL <->UI
We stuck the ninject configuration in the BL. Since the Bl is the only layer that References the DAL. We exposed the DAL interfaces/concrete classes to the BL via references. Then in the BL we added the Ninject Configuration.
Once that was done in the UI we were able to access all of the Business objects.
ninject starter tutorial
DAL
public interface IRepository
{
//does some things
}
public SQLBlogRepository : IRepository
{
//implements IRepository
}
BL
NINJECT CONFIGURATION FILE
public Foo : IFOO
{
public Foo(IRepository steve){}
}
public interface IFOO
{
}
public class NinjectConfig : NinjectModule
{
public override void Load()
{
Bind<IRepository>.To<SQLBlogRepository>();
Bind<IFOO>.To<Foo>();
}
}
then you use it like so.
var repo = new StandardKernel(new NinjectConfig()).Get<IRepository>();
var fooManager = new StandardKernel(new NinjectConfig()).Get<IFOO>();
The var fooManager, through the power of ninject will autoInstantiate your repo. So you do not need to create it yourself. The config file will handle all the dependancies in the constructor. So you never need to know what constructor creations you need to do. And you can also change the creations in one spot and propagate it out automagically through your code.
In your sample the UI (Mvc Project) is your Composition Root and you can config your dependency in it (with any ioc container like ninject). Your mvc project must have a reference to BLL and DAL layer and you must make a mapping like #gh9 answer in your mvc project.
In your controller you have
public class HomeController : Controller
{
private readonly IFOO _fooBll;
public HomeController(IFOO fooBll){
_fooBll=fooBll;
}
public ActionResult Index()
{
return View();
}
}
and you must have a controller factory to resolve your controller dependency like :
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel ninjectKernel;
public NinjectControllerFactory()
{
ninjectKernel = new StandardKernel();
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return controllerType == null
? null
: (IController) ninjectKernel.Get(controllerType);
}
}
Related
I have a C# & ASP.NET MVC project using a Repository pattern with Ninject.
The current controller has all the injections for my data repositories that I guess I have to keep away of the System.Web assembly, because the data repository should only know about database and nothing else.
After reviewing my code I see that I have a dependency on AppStateProvider:
public class AppStateProvider : IAppStateProvider
{
public Profile AppState
{
get
{
Profile appState = null;
if (HttpContext.Current != null && HttpContext.Current.Session["appstate"] != null)
{
appState = (Profile )HttpContext.Current.Session["appstate"];
}
return appState;
}
}
}
This dependency is registered in my NinjectWebCommon.cs:
kernel.Bind(typeof(IAppStateProvider)).To(typeof(Helpers.AppStateProvider));
The concrete class AppStateProvider lives inside my Web project in a Helpers folder.
Now, on my data project I have the following repository that injects the dependency.
public class EmployeeRepository : IEmployeeRepository
{
ILogManager _logManager = null;
private readonly Profile _appState;
public EmployeeRepository (IAppStateProvider appStateProvider, ILogManager logManager)
{
_appState = appStateProvider.AppState;
_logManager = logManager;
}
// some methods here!!
}
So, I guess I'm doing the correct way because Data Repository still doesn't know anything about the application context (HttpContext) and If I reference the same Data Repository from a Windows Service project then my concrete class that will be injected instead of calling HttpContext to get the session might call database or other place to get the Profile object property. Am I correct?
Is there a way that instead of having this extra dependency AppStateProvider I can pass to the dependencies from my controller to the Profile object without passing it to each method as a parameter, like passing it as a property object maybe?
The shown design already separates concerns via abstractions.
The composition root of the windows service project would just need to register the desired concrete implementation.
For example
//At the Composition Root of Windows Service
//...
windowsServiceKernel
.Bind(typeof(IAppStateProvider))
.To(typeof(WindowsServiceAppStateProvider));
//...
Where the concrete WindowsServiceAppStateProvider implementation lives inside the windows service project.
The data repository already explicitly states its required dependencies via constructor injection.
Nothing else really to be changed here.
I am working on a .net core project where each controller has their own service as DI. All those services share some common stuff so I abstract a BaseService class:
public class BaseService
{
public BaseService(IHttpContextService srv)
{
...
}
}
This BaseService, or in another word, all the services need another service for the HTTP context.
Now I need to inherit from this BaseService if I need a new service for a new controller:
public class MyFirstService : BaseService
{
public MyFirstService(IHttpContextService srvHttp, AdditionalService srvAdditional) {}
}
In its constructor, I will need to specify the IHttpContextService again, and a few additional services this MyFirstService needs.
But this seems wrong because the child is a descendant and therefore should have the IHttpContextService naturally. Not to mention the child doesn't have a constructor with the same parameters as the ancestor which gives a compile error.
Is there a way to DI objects outside of the constructor? Or just get rid of the DI from .net core? Or I should change my design pattern?
I've read the Armen Shimoon's article ASP.NET Core: Factory Pattern Dependency Injection and I've decided to solve my ASP.NET Core DI problem using the technique suggested by him.
I’ve got a generic interface:
public interface IItemRepository<out T> where T : BaseItem
and its generic implementation:
public class ItemRepository<T> : IItemRepository<T> where T : BaseItem
I register it with:
services.AddSingleton(typeof(IItemRepository<>), typeof(ItemRepository<>));
But for Currency I’ve got a specific implementation:
public class CurrencyRepository : ItemRepository<Currency>
(Curency is of the BaseItem type.) What I want is to register
CurrencyRepository
for
IItemRepository<Currency>
and
ItemRepository<T>
for all other items that implement BaseItem. I created a factory class to accomplish this:
public class ItemRepositoryFactory : IServiceFactory> where T : BaseItem
{
private readonly ApplicationDbContext _context;
public ItemRepositoryFactory(ApplicationDbContext context)
{
_context = context;
}
public ItemRepository Build()
{
if (typeof(T) == typeof(Currency))
return new CurrencyRepository(_context) as ItemRepository;
return new ItemRepository(_context);
}
}
but I don’t know how to register it with IServiceCollection. Or maybe I’m not on the right way at all?
You can't register it explicitly. ASP.NET Core DI is meant to be simple and offer out of box DI/IoC experience and easy for other DI/IoC containers to plugin.
So the built-in IoC doesn't offer Auto-Registrations, Assembly scanning, Decorators or registration of all interfaces/sub types of the class.
For concrete implementations, there is a "workaround"
services.AddScoped<IMyService,MyService>();
services.AddScoped<MyService>(provider => provider.GetService<IMyService>());
Then both MyService and IMyService inside a constructor would receive the same instance of the class.
But this doesn't work with open generics and is a manuell process. For automatic discovery or registration you need a 3rd party IoC container, such as Autofac, StructureMap etc.
But in your concrete sample it should be enough to register IItemRepository<Currency> inside your ConfigureServices method
services.AddScoped<IItemRepository<Currency>,CurrencyRepository>();
But actually the open generic should cover this case already, if you inject IItemRepository<Currency> into your services.
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.
I have 'standard' MVC application in next structure: UI (MVC), Business logic and data access using FluentNHibernate. I've done all steps for registering in castle container my components as described in castle documentation, used FluentRegistration API. So, all components were registered using WIndsor Installers like this:
container.Register(Classes.FromThisAssembly()
.BasedOn(typeof(IHandlerBase<>))
.WithService.AllInterfaces()
.LifestyleTransient());
In this code IHandlerBase - generic interface from which derives all my nested classes in business logic. Data access registered in same way and when I start my app all my components and services registered in container. All dependencies in MVC project relatively to BL resolved, but when I need my dependencies in business logic relatively to DataAccess they didn't. Stub example of my modules:
MVC
public ILogger Logger { get; set; } // Resolved, not null
public IHandlerBase<FooRerquest> FooHandler<FooRequest> { get; set; } // Resolved, not null
// Call Foohandler method
FooHandler.MethodName() { ... } // Here works fine
BusinessLogic
public ILogger Logger { get; set; } // Unresolved, null
public IRepository <FooCommand> FooRepository<FooCommand> { get; set; } // Unresolved, null
// Call FooRepository method
FooRepository.MethodName() { ... } // Doesn't work, catch ArgumentNullException
ILogger is a Castle NLog Facility
What and where I do in wrong way?
Thanks, Andrew
It works in UI because Controllers are created via custom ControllerFactory which uses container usually.
If instances of your business logic classes are resolved as part of MVC classes, they should be resolved. If simply constructors are used to create instances of your business logic classes then they know nothing about IoC and all references can't be resolved.
I suggest you use constructor injection since it makes Dependency Injection more visible.