I am trying to Bind two concrete classes to one interface. What command should I use in Ninject to do that? What I am trying to do is to Bind two concrete classes to one interface base on the controller Name. Is that possible? I suppose that in ninject you use the .When to give the conditional but there is no tutorial out there where they show you how to use the .When for ninject.
Here are few examples. Check out Ninject source project and its Tests subproject for various samples of usage, that's the best documentation for it, especially since docs haven't been updated for v2 yet.
// usage of WhenClassHas attribute
Bind<IRepository>().To<XmlDefaultRepository>().WhenClassHas<PageAttribute>().WithConstructorArgument("contentType", ContentType.Page);
// usage of WhenInjectedInto
Bind<IRepository>().To<XmlDefaultRepository>().WhenInjectedInto(typeof(ServicesController));
Bind<IRepository>().To<XmlDefaultRepository>().WhenInjectedInto(typeof(PageController)).WithConstructorArgument("contentType", ContentType.Page);
Bind<IRepository>().To<XmlDefaultRepository>().WhenInjectedInto(typeof(WidgetZoneController)).WithConstructorArgument("contentType", ContentType.WidgetZone);
// you can also do this
Bind<IRepository>().To<PageRepository>().WhenInjectedInto(typeof(PageController)).WithConstructorArgument("contentType", ContentType.Page);
Bind<IRepository>().To<WidgetZoneRepository>().WhenInjectedInto(typeof(WidgetZoneController)).WithConstructorArgument("contentType", ContentType.WidgetZone);
// or this if you don't need any parameters to your constructor
Bind<IRepository>().To<PageRepository>().WhenInjectedInto(typeof(PageController));
Bind<IRepository>().To<WidgetZoneRepository>().WhenInjectedInto(typeof(WidgetZoneController));
// usage of ToMethod()
Bind<HttpContextBase>().ToMethod(context => new HttpContextWrapper(HttpContext.Current));
HTH
Related
DISCLAIMER: This is a general question about Dependency Injection without having to do with any specific product/project/DI-Solution. This question in no way is asking to compare features between DI solutions.
I am using DI in ASP.NET MVC 5 Project using SimpleWebInjector. Everything works cool as can be, my controllers have ctors that have parameters which have values injected properly, those dependencies have their own ctors that are getting params injected fine.
Now here is the peculiar scenario: One of the dependencies have a ctor parameter that can only be injected with a value provided to all Actions of my controller. How can I accomplish that? Is that even possible with DI?
One of the dependencies have a ctor parameter that can only be injected with a value provided to all Actions of my controller.
If the value is provided to an action, that means that it is runtime data. Runtime data should not be injected in to the constructor of your components. This is an anti-pattern, as explained here. In short, the article can be summarizd as:
Don't inject runtime data into application components during construction; it causes ambiguity, complicates the composition root with an extra responsibility and makes it extraordinarily hard to verify the correctness of your DI configuration. My advice is to let runtime data flow through the method calls of constructed object graphs.
The article gives 2 general solutions:
pass runtime data through method calls of the API or
retrieve runtime data from specific abstractions that allow resolving runtime data.
See how Castle Windsor, my favorite DI container, provides what you need.
container.Register(
Component.For<IDBContext>().ImplementedBy<CustomDBContext>()
.DependsOn(Dependency.OnValue("connectionString", connectionString))
);
I'm a relatively new user of both Autofac and ASP.NET Core. I've recently ported a small project from a 'classic' ASP.NET WebAPI project to ASP.NET Core. I am having trouble with Autofac, specifically in registration of generic types.
This project uses a Command pattern, each command handler is a closed generic like
public class UpdateCustomerCommandHandler: ICommandHandler<UpdateCustomerCommand>
These command handlers are injected into the controllers like:
readonly private ICommandHandler<UpdateCustomerCommand> _updateCustomerCommand;
public ValuesController(ICommandHandler<UpdateCustomerCommand> updateCustomerCommand)
{
_updateCustomerCommand = updateCustomerCommand;
}
Autofac is configured (partially) as:
var builder = new ContainerBuilder();
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
//This doesn't seem to be working as expected.
builder.RegisterAssemblyTypes(assemblies)
.As(t => t.GetInterfaces()
.Where(a => a.IsClosedTypeOf(typeof(ICommandHandler<>)))
.Select(a => new KeyedService("commandHandler", a)));
The above does not seem to be registering the generic as expected. If I use the below method for registration, it works well.
builder.RegisterType<UpdateCustomerCommandHandler>().As<ICommandHandler<UpdateCustomerCommand>>();
When I say "It doesn't work", what I mean is that when attempting to instantiate the controller, I get "InvalidOperationException: Unable to resolve service for type 'BusinessLogic.ICommandHandler`1[BusinessLogic.UpdateCustomerCommand]' while attempting to activate 'AutoFac_Test.Controllers.ValuesController'."
This worked well in the Full WebAPI version of this project, but not after recreating it in ASP.NET Core. To be clear, this was working perfectly well before porting to ASP.NET Core.
Here is a link to the code that I've used to recreate this issue:
https://dl.dropboxusercontent.com/u/185950/AutoFac_Test.zip
**** EDIT AFTER SOLUTION DISCOVERED ****
There was nothing in fact wrong with my Autofac configuration and certainly not Autofac itself. What had happened was that I had renamed the output of my dependent assemblies in an effort to make the assembly scanning stuff (replacing of AppDomain.CurrentDomain.GetAssemblies() more elegant, however I never modified the dependencies of the API project to reference the new assemblies. So Autofac was scanning the correctly loaded assemblies which happened to be the older versions, which did not contain the interfaces and implementations I expected...
Autofac has built-in support to register closed types of open-generic.
builder
.RegisterAssemblyTypes(ThisAssembly)
.AsClosedTypesOf(typeof(ICommandHandler<>));
This will scan your assembly, find types that close the open generic ICommandHandler<> interface, and register each of them against the closed generic interface they implement - in your case, ICommandHandler<UpdateCustomerCommand>.
What doesn't work in your example is that you associate a key to your services. Autofac doesn't look for the keyed version of your ICommandHandler<UpdateCustomerCommand> when trying to instantiate the ValuesController, which is why you get the exception.
Edit after QuietSeditionist's comment:
I'll try to elaborate a bit on the keyed vs. default services. The way you registered your handlers is by associating the commandHandler key to them.
This means that once the container is built, here's the only way you can resolve such a handler:
// container will look for a registration for ICommandHandler<UpdateCustomerCommand> associated with the "commandHandler" key
container.ResolveKeyed<ICommandHandler<UpdateCustomerCommand>>("commandHandler");
When instantiating ValuesController, Autofac doesn't look for a keyed registration of ICommandHandler<UpdateCustomerCommand>, because it wasn't asked to.
The equivalent code it's executing is - and you can try to run that code yourself to get the exception:
// BOOM!
container.Resolve<ICommandHandler<UpdateCustomerCommand>>();
The reason your second registration works is because you didn't key the service:
// No key
builder
.RegisterType<UpdateCustomerCommandHandler>()
.As<ICommandHandler<UpdateCustomerCommand>>();
// commandHandler key
builder
.RegisterType<UpdateCustomerCommandHandler>()
.Keyed<ICommandHandler<UpdateCustomerCommand>>("commandHandler");
But since you don't want to register all your handlers one by one, here's how to register them without keying them:
builder
.RegisterAssemblyTypes(ThisAssembly)
.AsClosedTypesOf(typeof(ICommandHandler<>));
/Edit
I can see two scenarios where keying services can be useful:
You have several types implementing the same interface and you want to inject different implementations in different services. Let's say, you register both SqlConnection and DB2Connection as IDbConnection. You then have 2 services, one which is supposed to target SQL Server, the other one DB2. If they both depend on IDbConnection, you want to make sure you inject the correct one in each service.
If you use decorators, the way registrations work is you define the services to which the decorators will apply by a key - the first example is self-explanatory
Because Google brings you to this page even when you're trying to manually register types, I thought that even though this doesn't answer the asked question, it would be useful for future visitors. So, if you want to manually register a generic type, you would use this format:
service.AddTransient(typeof(IThing<>), typeof(GenericThing<>));
or if there's no interface, then just:
service.AddTransient(typeof(GenericThing<>));
and for completeness, if you have a generic with multiple types:
services.AddTransient(typeof(GenericThing<,>));
I have a base controller from which inherit all my controllers. This base controller has some properties I'd like to inject the using property injection.
My controller registration looks like this
builder.RegisterControllers(Assembly.GetExecutingAssembly()
I don't know how to access the base class and inject the properties.
This should work:
builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
Some more info on the autofac website: http://code.google.com/p/autofac/wiki/PropertyInjection
You may want to consider using an Autofac Aggregate Service:
An aggregate service is useful when you need to treat a set of dependencies as one dependency. When a class depends on several constructor-injected services, or have several property-injected services, moving those services into a separate class yields a simpler API.
An example is super- and subclasses where the superclass have one or more constructor-injected dependencies. The subclasses must usually inherit these dependencies, even though they might only be useful to the superclass. With an aggregate service, the superclass constructor parameters can be collapsed into one parameter, reducing the repetitiveness in subclasses. Another important side effect is that subclasses are now insulated against changes in the superclass dependencies, introducing a new dependency in the superclass means only changing the aggregate service definition.
This works for me:
using Autofac;
using Autofac.Integration.Web;
using Autofac.Integration.Web.Mvc;
builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();
builder.RegisterControllers(Assembly.GetExecutingAssembly()).InjectActionInvoker();
nickvane's answer is correct. Just make sure
builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
is after your all dependencies are registered. Or in other words, just right before you build your container.
So final code will look like
.
.
.
builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
var container = builder.Build();
Need to call also for MVC:
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
For Web API:
HttpConfiguration config = GlobalConfiguration.Configuration;
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
I have a custom attribute class derived from AuthorizationAttribute, which performs custom security on controller actions. The OnAuthorizationCore method depends on various other components (e.g. DAL) in order to ajudicate whether a user can invoke an action.
I'm using Autofac for dependency injection. The ExtensibleActionInvoker claims to be able to perform property injection on action filters. Setting an attribute's properties at runtime (which seems like a bad idea) will work in a simple unit test, but in a busy, multi-threaded web server it's bound to go wrong, and so this idea seems like an anti-pattern. Hence this question:
If my AuthorizationAttribute depends on other components in order to work correctly, what it the right [architecture] pattern in order to achieve this?
i.e. AuthorizationAttribute depends on IUserRepository... how should this relationship be resolved?
The ExtensibleActionInvoker claims to be able to perform property injection on action filters.
Correct - but don't confuse action filters with the attributes that might not implement them. The cleanest way to approach this in ASP.NET MVC is to split responsibilities, even though the MVC framework allows you to combine them.
E.g., use a pair of classes - an attribute class that holds data only:
// Just a regular old attribute with data values
class SomeAttribute : Attribute { ... }
And a filter that has dependencies injected:
// Gets dependencies injected
class SomeFilter : IActionFilter { ... }
SomeFilter just uses the typical approach of getting the SomeAttribute attribute from the controller or action method via GetCustomAttributes() to do whatever work is needed.
You can then use ExtensibleActionInvoker to wire up the filter:
builder.RegisterControllers(...).InjectActionInvoker();
builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();
builder.RegisterType<SomeFilter>().As<IActionFilter>();
It might be a little more code than you'd write using the attribute-as-filter approach, but the quality of the code will be better in the long run (e.g. by avoiding the limitations of attributes and the awkwardness of the Service Locator solutions.)
I would seem that the easiest way to achieve this is to bite the bullet and accept a dependency on autofac itself. While a dependency on the IoC is in itself an anti-pattern, it's somewhat more pallatable. You can implement a property as follows:
public class UserAuthorizeAttribute : AuthorizeAttribute
{
public IUserRepository CurrentUserService
{
get
{
var cpa = (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance;
var cp = cpa.ContainerProvider;
return cp.RequestLifetime.Resolve<IUserRepository>();
}
}
}
...
There's no straight-forward way to do this prior to MVC2. There is an interesting technique detailed here: http://www.mattlong.com.au/?p=154. I'd suggest using the Common Service Locator to abstract over this and locate your DI container.
If you're using MVC 3 then you can use MVC Service Location
Constructor injection seems to be impossible w/o changing way of filter registration.
Even in Asp.Net Mvc3:
One place where dependency injection has been difficult in the past is inside the filter attributes themselves. Because the .NET framework runtime is actually responsible for creating these attribute instances, we cannot use a traditional dependency injection strategy.
So - next best thing is property injection (Mvc3 provides some support for that out of the box).
Here's a how to for doing that manually.
I personally use MvcExtensions. I'm fine with registering them in different way. Here's usage.
Another thing You might want to investigate is MvcTurbine project. In contrast to MvcExtensions project which is more general - MvcTurbine is primarily for providing dependency injection support.
I recently followed Stephen Walther through creating a generic repository for your data models using the Entity Framework with the following link, http://bit.ly/7BoMjT
In this blog he briefly talks about creating a generic repository and why it's suggested to do so (to be clear of friction). The blog itself doesn't go into great detail on how to inject the GenericRepository into your project for that you'll need to download his source code of Common Code. However, once I finally understood the importance of the Repository pattern, and how it makes a difference in the data models I create in ASP.Net MVC I was wondering if I could do something similar to my Controllers and Views?
Can I create a ControllerRepository or ControllerFactory(as I've Bing'd it) and create a generic controller with 5 ActionResults and depending on what I inject into my GenericRepository datamodel (i.e. I have DellXPSComputers, GateWayComputers, HPComputers as a single db datamodel)
And actually have only one controller besides the Generic one I create that will go and grab the right datamodel, and view?
If so, what is the best way to implement this?
You could create a generic controller factory, but I don't see many scenarios why you'd ever want to. Except in your tests and redirects, you'd never be calling a controller method directly (vs. a repository method which you're calling in many places).
Yes! You absolutely can!
I've done it in the past with great success. The result is that you end up with a web application layer surfacing your repos with almost no code (just what's necessary to provide CRUD services for your entities).
Ultimately, you'll end up with something like this in your implementation of CreateController:
Type controllerType = controllerbase.MakeGenericType(entityType, datacontextType);
var controller = Activator.CreateInstance(controllerType) as IController;
return controller;
Wiser men than me would use a IOC framework to inject the types, I'm using plain old reflection and reading the type names out of the route values in URLs like:
http://computer/repo/entityname/by/fieldname/value.html
Good luck!