Resolving multiple services using constructor injection with Windsor in MVC3 - asp.net-mvc

I have a controller that takes an instance of ICustomerService. The constructor for one of my implementations (ok, the only implementation atm) takes an array of ICustomerExporter instances.
I'm registering all implementations of ICustomerExporter using the following code:
_container.Register(AllTypes
.FromAssembly(typeof(ICustomerExporter).Assembly)
.BasedOn<ICustomerExporter>().LifestyleSingleton());
And my DefaultCustomerService implementation looks like:
public DefaultCustomerService(ISession session, ICustomerExporter[] exporters)
{
this._session = session;
this._exporters = exporters;
}
However, when I try to run the app, I get the following error:
PM.Services.Implementation.DefaultCustomerService' is waiting for the following
dependencies: - Service 'PM.Services.ICustomerExporter[]' which was not registered.
Well pretty clearly it IS registered, I can even stop in the debugger and verify in the container's component list that the ExcelCustomerExporter implementation is there. So why am I getting this error message?

Looks like you're registering for ICustomerExporter, but I don't know that Windsor will assume that an implementation of ICustomerExporter will always satisfy your ICustomerExporter[] dependency. Have you tried registering a ICustomerExporter[] dependency also?

Just to answer this question for anyone who comes along, when registering multiple services like this, you must do 2 things:
Register the ArrayResolver with the kernel prior to registering types
Make sure to tell the kernel to use the interface as the service base.

Related

Issue registering generic types with Autofac in ASP.NET Core

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<,>));

MVC Dependency resolver conditional

I am using dependency resolver and i have added my unity container to the same. So by default "GoldCustomer" gets injected in to the "CustomerController" as per the current container rules.
IUnityContainer oContainer = new UnityContainer();
oContainer.RegisterType<ICustomer, GoldCustomer>(); // injects GoldCustomer
DependencyResolver.SetResolver(new UnityDependencyResolver(oContainer));
If i want to change by current container configuration i can always create new Container and set it and call the SetResolver again. I know that the above code should be configurable via XML config but still if we need to pickup new container objects we have to still call the setresolver.
Is this the right way or are there better ways of changing container depedency rules while the application running.
Second what are the events where we can change the container is it session_start , httphandler's or something better.
Firstly why would you need multiple containers? It must be the singleton object who keeps all the dependency registered since the application started.
In a practice I would say keep single container and if required create multiple Registration function in separate assemblies and invoke all of them in a AppBootstrapper.
If it's an application then best way is to use the Application start with Async behaviour so that the startup doesn't get affected.
======================================================
Unfortunately the Named registration is the only option and Unity required to register with names explicitly. Thats why I personally like DI containers like Autofac and SimpleInjector. They are fast and They allow multiple registrations of an Interface with multiple Types and the resolver uses Type resolver and Named resolver methods without explicitly asking for Names and those resolvers are overridable too.
I am not sure why it does not look that complex to me , If I understand question quickly I can do it as follows,
assume that I have interface IMovieRepository and two classes implementing it EnglishMovieRepository and HindiMovieRepository.
How about resolving them as in UnityConfig.cs as follows,
If(condition)
{
container.RegisterType<IMovieRepository, EnglishMovieRepository>();
}
else
{
container.RegisterType<IMovieRepository, HindiMovieRepository>();
}
If requirement is something different then please let me know
Thanks
/dj

Can Autofac return all services for a type in the same order they were registered?

I'm contributing to an open source project that is looking to support multiple containers for its internal services. One of the requirements for supported containers is that order of registration matters. So, if several implementations of an interface are registered in a particular order, when a list of those services is resolved, the implementations should be returned in the same order they were registered.
var builder = new ContainerBuilder();
builder.RegisterType<PreferredService>().As<IService>();
builder.RegisterType<AlternativeService>().As<IService>();
builder.RegisterType<AdditionalService>().As<IService>();
...
// Get the first (preferred) implementation of IService.
var possibleServices = container.Resolve<IEnumerable<IService>>();
IService idealServiceImplementation = possibleServices.FirstOrDefault();
My testing shows that Autofac returns the services is reverse order. Is this always the case? Can I trust they will resolve in reverse order every time? Will this behavior be consistent even if I register some of the later services after other registrations for different interfaces? Can I intercept implicit calls to Resolve for lists?
Is there a way to instruct Autofac that registration order matters?
Autofac registrations are always "last registration wins" unless you use PreserveExistingDefaults(). A quick look into the implementation shows that registrations are stored as a linked list where the default behavior adds to the beginning and PreserveExistingDefaults() adds to the end. Resolving a single service gets you the first item in the list. Resolving enumerable gets you that order. I'm not sure if that behavior is guaranteed to never change.
If it were me, I'd depend on the current behavior, but write an automated test that will fail if the behavior changes.

StructureMap specific constructor - how should parameters be initialized?

Given the following piece of a StructureMap registry
For<ILogger>().Use(LogFactory.CreateLogger());
For<Scheduler>().Use(() => new Scheduler(ObjectFactory.GetInstance<ILogger>()));
...is this a good way of providing an ILogger to the Scheduler? It works - but I'm curious to know if it's a poor way of providing a type that the container is configured to provide, or whether it's my only option given the scenario... the scenario being that the Scheduler type itself has other constructors which I cannot change, nor do I care for - but they are needed, so I need to specify this particular constructor rather than using a straight For<x>().Use<y>();
It would be best if the registered service has exactly one public constructor. This makes it unambiguous what dependencies a service makes and makes it very clear which constructor will be selected by the container, and it allows you to register types using the more flexible Use<T>(), and makes the composition root less likely to be changed when the constructor changed.
However, as you said, in your case you can't change the constructors of that type, so you will have to fall back. There are multiple ways to select the proper constructor with StructureMap, but registering a delegate is the best way, since this gives you compile time support.

Construtor/Setter Injection using IoC in HttpHandler, is it possible?

I've ran into a rather hairy problem. There is probably a simple solution to this but I can't find it!
I have a custom HttpHandler that I want to process a request, log certain info then enter the details in the database. I'm using NUnit and Castle Windsor.
So I have two interfaces; one for logging the other for data entry, which are constructor injected. I quickly found out that there is no way to call the constructor as the default parameterless constructor is always called instead.
So I thought I would use Setter injection and let Castle windsor sort it out. This actually works as when I use container.Resolve<CustomHttpHandler>(); I can check that the logger is not null. (In Application_Start in Global.asax.cs)
The problem is although Castle Windsor can create the instance the http application is not using it??? I think??
Basically the whole reason for doing it this way was to be able to test the logger and data repository code in isolation via mocking and unit testing.
Any ideas how I can go about solving this problem?
Thanks!
Not possible, at least not directly. IHttpHandler objects are instantiated by the ASP.NET runtime and it doesn't allow Windsor to get involved in its creation. You can either:
Pull dependencies, by using the container as a service locator.
Set up a base handler that creates, injects and delegates to your own handlers (see how Spring does it)
Use the container as a service locator for another service that handles the entire request (as saret explained)
What you could do is have the HttpHandler call out to another object that actually handles the request. so in your HttpHandler's ProcessRequest method you would do something like this:
public void ProcessRequest(HttpContext context)
{
var myHandlerObject = container.Resolve<HandlerObject>();
myHandlerObject.ProcessRequest(context or some state/info that is required)
}

Resources