Entity Framework 4, Ninject 3, MVC3
Currently in my web app i have been using a rather rudimentary approach to per request instantiation of an Object Context. So I am experimenting with Ninject, and some old sample code, but I am unsure how to proceed with the following..
Effectively I want to be able in the controller to do the equivalent of: DB_Entities.Current.Albums ... Should i be instantiating a StandardKernel every time?
The sample i was looking at was using the following: MvcApplication.Container.Get(); but in Ninject 3 with the App_Start hookup I dont have access to Container..
My attempt to replicate the above line, is failing at runtime.
using MusicStoreEntities;
using Ninject;
using TestMVC3WithIOC.App_Start;
using System.Data.Objects;
namespace TestMVC3WithIOC.Models
{
public partial class MusicStoreEntities
{
public static MusicStoreEntities Current
{
get
{
using (IKernel kernel = new StandardKernel())
{
return (MusicStoreEntities)kernel.Get<ObjectContext>();
}
}
}
}
}
Also, note, that in App_Start\NinjectWebCommon.cs I have the following modification:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ILogger>().To<NLogger>();
kernel.Bind<ObjectContext>().To<MusicStoreEntities>().InRequestScope();
}
Although a workable solution, it seems ill-advised to pass the entire Kernel into a class, because it tends to obscure the classes actual, specific dependencies. A better approach is to pass a factory dependency into your controller's constructor.
public partial class MusicStoreEntities
{
private readonly IEntitiesFactory _factory;
public MusicStoreEntities(IEntitiesFactory factory)
{
_factory = factory;
}
}
IEntitiesFactory has a simple implementation with a single method GetObjectContext().
(I believe also the "Unit of Work" pattern is popular at the moment, but I can't really speak to that as I haven't used it. Maybe worth looking into.)
Related
Update: Is there a way to achieve what I'm trying to do in an IoC framework other than Windsor? Windsor will handle the controllers fine but won't resolve anything else. I'm sure it's my fault but I'm following the tutorial verbatim and objects are not resolving with ctor injection, they are still null despite doing the registers and resolves. I've since scrapped my DI code and have manual injection for now because the project is time sensitive. Hoping to get DI worked out before deadline.
I have a solution that has multiple classes that all implement the same interface
As a simple example, the Interface
public interface IMyInterface {
string GetString();
int GetInt();
...
}
The concrete classes
public class MyClassOne : IMyInterface {
public string GetString() {
....
}
public int GetInt() {
....
}
}
public class MyClassTwo : IMyInterface {
public string GetString() {
....
}
public int GetInt() {
....
}
}
Now these classes will be injected where needed into layers above them like:
public class HomeController {
private readonly IMyInterface myInterface;
public HomeController() {}
public HomeController(IMyInterface _myInterface) {
myInterface = _myInterface
}
...
}
public class OtherController {
private readonly IMyInterface myInterface;
public OtherController() {}
public OtherController(IMyInterface _myInterface) {
myInterface = _myInterface
}
...
}
Both controllers are getting injected with the same interface.
When it comes to resolving these interfaces with the proper concrete class in my IoC, how do I differentiate that HomeController needs an instance of MyClassOne and OtherController needs an instance of MyClassTwo?
How do I bind two different concrete classes to the same interface in the IoC? I don't want to create 2 different interfaces as that breaks the DRY rule and doesn't make sense anyway.
In Castle Windsor I would have 2 lines like this:
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassOne>());
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassTwo>());
This won't work because I will only ever get a copy of MyClassTwo because it's the last one registered for the interface.
Like I said, I don't get how I can do it without creating specific interfaces for each concrete, doing that breaks not only DRY rules but basic OOP as well. How do I achieve this?
Update based on Mark Polsen's answer
Here is my current IoC, where would the .Resolve statements go? I don' see anything in the Windsor docs
public class Dependency : IDependency {
private readonly WindsorContainer container = new WindsorContainer();
private IDependency() {
}
public IDependency AddWeb() {
...
container.Register(Component.For<IListItemRepository>().ImplementedBy<ProgramTypeRepository>().Named("ProgramTypeList"));
container.Register(Component.For<IListItemRepository>().ImplementedBy<IndexTypeRepository>().Named("IndexTypeList"));
return this;
}
public static IDependency Start() {
return new IDependency();
}
}
I hope you can use service overrides.
Ex.
container.Register(
Component.For<IMyService>()
.ImplementedBy<MyServiceImpl>()
.Named("myservice.default"),
Component.For<IMyService>()
.ImplementedBy<OtherServiceImpl>()
.Named("myservice.alternative"),
Component.For<ProductController>()
.ServiceOverrides(ServiceOverride.ForKey("myService").Eq("myservice.alternative"))
);
public class ProductController
{
// Will get a OtherServiceImpl for myService.
// MyServiceImpl would be given without the service override.
public ProductController(IMyService myService)
{
}
}
You should be able to accomplish it with named component registration.
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassOne>().Named("One"));
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassTwo>().Named("Two"));
and then resolve them with
kernel.Resolve<IMyInterface>("One");
or
kernel.Resolve<IMyInterface>("Two");
See: To specify a name for the component
Typically DI containers follow Register, Resolve and Release patterns. During the register phase there are two steps. The first is to specify the mapping as you are doing. The second step is to specify the rules which govern which to inject where.
This problem is very common when we try to address Cross cutting concerns using decorators. In these situations, you have multiple classes(decorators) implementing a single interface.
Briefly, we need to implement IModelInterceptorsSelector which allows you to write imperative code that decides which Interceptor to apply to which types or members.
This is elaborately described in the book Dependency Injection in .Net book by Mark Seemann. Look for chapter 9 interception or search for the above interface.
I am not an expert at this, but was searching for the exact same problem and found the ans in the above book.
Hope this helps.
Regards
Dev1
I'm trying to inject a second repository into my asp.net mvc 3 controller. And I cant get it to work, not sure where to "add another" using Ninject.
I have a void function in global.asa.cs
kernel.Bind<INewsRepository>().To<NewsRepository>();
And in my controller I have:
private INewsRepository _newsRepository;
private IContentRepository _contentRepository;
public NewsController(INewsRepository newsRepository, IContentRepository contentRepository)
{
this._newsRepository = newsRepository;
this._contentRepository = contentRepository;
}
How can I register IContentRepository for the NewsController as well?
I use autofac instead of Ninject but the basics stay the same.
If you got your first dependency injection working then you should be able to bind others as well. You just have to add a new binding in Application_Start() in your Global.asax.
So under your first binding do this as well:
kernel.Bind<IContentRepository>().To<ContentRepository>();
You can have as many bindings as you like.
First off it's a good practice to move the bootstrapping of your application into a separate location. This keeps your Global.asax clean.
You should also be using convention based registration. It will end up saving you lots of time for the bindings you don't need to customize.
So for you I'd probably suggest the following
public static class Bootstrapper()
{
public static void Bootstrap()
{
kernel.Scan( k =>
{
k.FromAssemblyContaining<INewsRepository>();
k.BindWithDefaultConventions();
});
}
}
And in your Global.asax you add this..
Bootstrapper.Bootstrap();
Then I would suggest you spend some time on Google reading about ninject conventions.
I use the nuget template way of ninjectning my MVC3 app,
which means I have use WebActivator to invoke a method on a static class that in turn creates a Ninject bootstrapper and hooks up to MVC3.
That works fine for Controller, adapters etc. But I want to have another Webactivator activated class which gets its dependencies using Ninject.
I got it to work with a poor mans solution, but I would prefer a more elegant solution.
First I make sure my Webactivator class uses the PostApplicationStartMethod invoke, since the Ninject module uses the PreApplicationStartMethod I can ensure that ninject has been loaded and is ready to go.. THen in the Start method I do
var workers = DependencyResolver.Current.GetServices<IWorker>();
To get my dependencies, the whole class looks like this
[assembly: WebActivator.PostApplicationStartMethod(typeof(SHB.DALA.Web.App_Start.WorkflowRunner), "Start")]
namespace SHB.DALA.Web.App_Start
{
public static class WorkflowRunner
{
public static void Start()
{
var workers = DependencyResolver.Current.GetServices<IWorker>();
//Do stuff with worker collection
}
}
}
There must be a more elegant solution right?
WebActivator (ASP.NET really) doesn't have any knowledge of Ninject project and therefore cannot have any parameters injected. You would need a Ninject WebActivator extension (the same way you have a Ninject MVC extension) to achieve it. But frankly this is a bit of a catch-22: you want WebActivator to setup Ninject and at the same time Ninject to setup WebActivator.
I can think of 2 possible scenarios for you:
leave the code as it is - I honestly don't know why you don't like your WorkflowRunner class. It is a nice, small class, no other code has any dependency on it, You obtain your references through a DependencyResolver which abstracts you from Ninject itself, your workflow initialization is nicely encapsulated there. I do not smell anything wrong here, really.
Initialize your workflows in the other WebActivator class, where setup Ninject. You know there that your Ninject is initialized and you can still keep workflow initialization code in a separate class.
I would obviously choose 1. if I were you.
If you already have the Ninject bootstrapper working, are you sure you need another solution? For non-controller dependencies, I use a BindingFactory class which has a GetInstance() method. This just calls the Get() method on the Kernel object.
public class BindingFactory
{
private static readonly IKernel Kernel = new StandardKernel(new DefaultServices());
public static T GetInstance<T>()
{
return Kernel.Get<T>();
}
public static IController GetControllerInstance(Type controllerType)
{
return Kernel.Get(controllerType) as IController;
}
}
I then use a NinjectControllerFactory which utilises the BindingFactory.
public class NinjectControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext context, Type controllerType)
{
if (controllerType == null)
return null;
return BindingFactory.GetControllerInstance(controllerType);
}
}
So I'm thinking you could just adapt your current implementation.
I have the following code:
public abstract class BaseController : Controller
{
public IUserService UserService { get; set; }
}
All my controllers inherit from this base controller. I started out by configuring it in Ninject using the following code:
kernel.Bind<BaseController>()
.ToSelf()
.WithPropertyValue("UserService", x => x.Kernel.GetService(typeof(IUserService)));
This did not work. I assume it is because of the fact that the BaseController is an abstract class (please confirm my assumption). So I moved on to modify the configuration to:
kernel.Bind<HomeController>()
.ToSelf()
.WithPropertyValue("UserService", x => x.Kernel.GetService(typeof(IUserService)));
This does work. The minor downside is that I now have to configure every controller the same way.
Since I also have DependencyResolver setup in my ASP.NET MVC 3 project I could also remove the above Ninject configuration and modify my base controller to look like:
public IUserService UserService
{
get
{
return DependencyResolver.Current.GetService<IUserService>();
}
}
Is there any benefit to using the fluent configuration as opposed to using the DependencyResolver approach? Is one better than the other? Which approach would be considered a better practice?
It is worth mentioning that I did not want to do constructor injection in my base controller.
A better practice in MVC it is to use constructor injection over property injection. Why did you make your choice like this ?
Using Constructor Injection you states that all dependencies in constructor are necessary for the class to do its job.
Property injection means that the dependencies are optional or that there are the local defaults implementations, so all will work even if you don't provide necessary implementations yourself.
You should really know what you're doing using Property injection or you have no other choice, so the safer approach is to rely on constructor injection.
Now I'll give you my point of view. Other may have other opinions.
DependencyResolver was introduced in MVC 3 for "convenient" service location but for me it's a regular Service locator which for me is also an anti-pattern http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx. I don't use it because I don't like it and there is no benefit in using it.
I prefer to user my controller factory like before and pass the dependencies through constructor.
More the IDependencyResolver has somme issues with some IoC containers (I don't know if it's the case with Ninject). You can read more here : http://mikehadlow.blogspot.com/2011/02/mvc-30-idependencyresolver-interface-is.html
If you need the same dependency in each controller then there seems to be something wrong in your design. Most likely you are handling some kind of cross cutting concern in your base controller. In this case Doing property injection is just treating sympthoms instead of cureing the disease. This should rather be handled by an aspect (e.g. a filter or an interceptor) so that you do not have to pollute your controller with something that does not belong there.
There are many ways to skin the cat they say. You could use conventions-based bindings with .WithPropertyValue() or with .OnActivaction() (as described here).
public class ControllerModule : NinjectModule
{
public override void Load()
{
// Get all controller types derived from the base controller.
IEnumerable<Type> controllerTypes = // ...
foreach (var controllerType in controllerTypes)
{
Bind(controllerType).ToSelf().InRequestScope()
.WithPropertyValue(...);
}
}
}
You could create your own custom implementation of the IInjectionHeuristic interface as described here or your own custom implementation of the IControllerActivator interface.
public class CustomNinjectControllerActivator : IControllerActivator
{
private readonly IKernel kernel;
public CustomNinjectControllerActivator(IKernel kernel)
{
this.kernel = kernel;
}
public IController Create(RequestContext context, Type controllerType)
{
var baseController = kernel.TryGet(controllerType) as BaseController;
if (baseController == null)
{
return null;
}
baseController.UserService = kernel.Get<IUserService>();
return baseController;
}
}
Heck, you could even use the service locator pattern if you are comfortable using it.
public IUserService UserService
{
get { return DependencyResolver.Current.GetService<IUserService>(); }
}
You should choose whichever solution is easiest to implement, test and maintain, and of course provides the desired behavior.
Using a DI container (in this case, Ninject) is it possible - - or rather, wise to cache a frequently used object for the entire application lifetime (or at least until it is refreshed)?
To cite example, say I have a Template. There are many Template objects, but each user will inherit at least the lowest level one. This is immutable and will never change without updating everything that connects to it (so it will only change on administration demand, never based on user input). It seems foolish to keep querying the database over and over for information I know is not changed.
Would caching this be best done in my IoC container, or should I outsource it to something else?
I already store ISessionFactory (nHibernate) as a Singleton. But that's a little bit different because it doesn't include a query to the database, just the back-end to open and close ISession objects to it.
So basically I would do something like this..
static class Immutable
{
[Inject]
public IRepository<Template> TemplateRepository { get; set; }
public static ITemplate Template { get; set; }
public void Initialize()
{
if(Immutable.Template == null)
{
Immutable.Template = TemplateRepository.Retrieve(1); // obviously better logic here.
}
}
class TemplateModule : Module
{
public void Load()
{
Bind<ITemplate>().ToMethod(() => Immutable.Initialize())InSingletonScope();
}
}
Is this a poor approach? And if so, can anyone recommend a more intelligent one?
I'd generally avoid using staticness and null-checking from your code - create normal classes without singleton wiring by default and layer that aspect on top via the container. Ditto, remove reliance on property injection - ctor injection is always better unless you have no choice
i.e.:
class TemplateManager
{
readonly IRepository<Template> _templateRepository;
public TemplateManager(IRepository<Template> templateRepository)
{
_templateRepository = templateRepository;
}
public ITemplate LoadRoot()
{
return _templateRepository.Retrieve(1); // obviously better logic here.
}
}
class TemplateModule : Module
{
public void Load()
{
Bind<ITemplate>().ToMethod(() => kernel.Get<TemplateManager>().LoadRoot()).InSingletonScope();
}
}
And then I'd question whether TemplateManager should become a ninject provider or be inlined.
As for the actual question... The big question is, how and when do you want to control clearing the cache to force reloading if you decided that the caching should be at session level, not app level due to authorization influences on the template tree? In general, I'd say that should be the Concern of an actual class rather than bound into your DI wiring or hardwired into whether a class is a static class or is a Singleton (as in the design pattern, not the ninject Scope).
My tendency would be to have a TemplateManager class with no static methods, and make that a singleton class in the container. However, to get the root template, consumers should get the TemplateManager injected (via ctor injection) but then say _templateManager.GetRootTemplate() to get the template.
That way, you can:
not have a reliance on fancy ninject providers and/or tie yourself to your container
have no singleton cruft or static methods
have simple caching logic in the TemplateManager
vary the Scoping of the manager without changing all the client code
have it clear that getting the template may or may not be a simple get operation
i.e, I'd manage it like so:
class TemplateManager
{
readonly IRepository<Template> _templateRepository;
public TemplateManager(IRepository<Template> templateRepository)
{
_templateRepository = templateRepository;
}
ITemplate _cachedRootTemplate;
ITemplate FetchRootTemplate()
{
if(_cachedRootTemplate==null)
_cachedRootTemplate = LoadRootTemplate();
return _cachedRootTemplate;
}
ITemplate LoadRoot()
{
return _templateRepository.Retrieve(1); // obviously better logic here.
}
}
register it like so:
class TemplateModule : Module
{
public void Load()
{
Bind<TemplateManager>().ToSelf().InSingletonScope();
}
}
and then consume it like so:
class TemplateConsumer
{
readonly TemplateManager _templateManager;
public TemplateConsumer(TemplateManager templateManager)
{
_templateManager = templateManager;
}
void DoStuff()
{
var rootTempalte = _templateManager.FetchRootTemplate();
Wild speculation: I'd also consider not having a separate IRepository being resolvable in the container (and
presumably having all sorts of ties into units of work). Instead, I'd have the TemplateRepository be a longer-lived thing not coupled to an ORM layer and Unit Of Work. IOW having a repository and a Manager none of which do anything well defined on their own isnt a good sign - the repository should not just be a Table Data Gateway - it should be able to be the place that an Aggregate Root such as Templates gets cached and collated together. But I'd have to know lots more about your code base before slinging out stuff like that without context!