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

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.

Related

In Spring4D is it possible to register generic interfaces?

I have classes that have a constructor such as
constructor Create(Factory: IFactory<IConnection>)
When I try and register the IFactory in the container
Container.RegisterType<IFactory<IConnection>,TConnectionFactory>
or
Container.RegisterType<TConnectionFactory>.Implements<IFactory<IConnection>>
I get an error stating that the interface does not have a guid.
I don't really want to add lots of pointless interfaces such as
IConnectionFactory = interface(IFactory<IConnection>)
['{45106BA8-43E7-4D26-B0EF-1639871B93E4}']
end;
to get around this but is this the only way?
Many thanks
As you found out the generic interface can have a GUID.
That itself causes no harm until you QueryInterface/Supports IList<string> from something that is an IList<Integer> which would erroneously succeed and subsequently fail once you start working with it. FWIW since you mentioned those types while the collection interfaces all have guids there is no need to ever do such querying when using them but they are required internally which then stays within the same generic type argument.
Currently the GUID is being used to check and get the interface from the implementing object because the RTL only supports doing that with a GUID and not with typeinfo.
In fact following code would not raise an exception during the registration but eventually cause defects when being resolved:
RegisterType<IFactory<IConnection>, TSomeFactory> where TSomeFactory implements IFactory<ISomethingElse>
However there is some rather hidden typeinfo available (see the commented line in System.TInterfaceTable) that has the exact typeinfo of the implemented interfaces. Spring4D internally uses that at some places, for example Spring.Reflection.TRttiTypeHelper.GetInterfaces.
That could be used but then there is another catch: generic types across multiple modules have different typeinfo. So it's not so easy to simply use that information to validate during registration and query the interface from the implementing class because right now the container (via some extension) supports registrations and dependencies across multiple modules.
Making the registration more robust and if possible remove the requirement for having a GUID on the interface is something I have on my list for the container refactoring which is planned for later this year.

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

Dependency management in Zend Framework 2 MVC applications

As the ServiceLocatorAwareInterface will likely be removed from the AbstractController in ZF3, dependencies should instead be passed via the constructor or via setter methods.
With this in mind, consider the use case of a user or site controller with actions such as register, activate account, login, logout, etc. At a minimum, this would require a UserService and 2 forms. Add a few more related actions (remote authentication, linking of accounts, etc.) and you end up with 4 or 5 forms.
Passing all these dependencies via the constructor would be messy at best, and more importantly, only 1 form is usually required per action.
Which one of the following techniques do you think is better, and why?
Create separate controllers for each action, so that each controller will only require a single form (in addition to a service). For example RegistrationController, LoginController, LinkAccountController, etc.
You end up with lots of controllers this way.
In the factory for the controller, supply different forms based on which action is being requested.
Construction of the controller becomes dependent on this factory, and more specifically the request environment (routing, etc.) You could construct the controller directly (for testing or whatever), but then you would need to ensure that the dependencies were available and throw exceptions if not.
Use the event manager, trigger an event in the controller when a form is required, and let an event handler supply the dependency on demand.
This technique is described here.
Your controller would then be dependent on an EventManager as opposed to a ServiceLocator, which is probably not much better.
Pass the FormElementManager to the controller, and request forms from it.
No better than the SL itself most likely.
Directly construct forms inside controllers.
How does this affect testibility?
The same question would then apply to handling a controller with multiple services (instead of forms).
Other?
See also:
Passing forms vs raw input to service layer
Factory classes vs closures in Zend Framework 2
First, ServiceLocator won't be removed. Maybe just the ServiceLocatorAwareInterface.
As you said, passing the FormElementManager is a solution and it's indeed better than passing the service locator. I'm personally using more and more plugin managers and they are a nice way to solving that kind of problem. A plugin manager is different that a service locator because it allows to retrieve only ONE type of objects (forms, hydrators, input filters...). Of course, as the parent service locator is injected into plugin managers, some people will do the trick of retrieving the service locator from plugin manager (taht's why I'd like to remove in ZF3 the service locator in plugin managers, and instead having a specific factory where the parent locator is passed for injections, although it would complicate a bit the factory interface :/...).
This, with splitting controllers into smaller controllers, should make your code cleaner.
By the way, you are talking about authentication, but imo if you correctly inject an authentication service (or inject the authentication service into a user service or something like that), it reduces significantly the dependencies into the controller.
You need to think about the problem you're trying to solve as a domain. In the User domain, there are many forms. So, aggregate them into a repository. The form repository would be passed into the user service, along with other repos like an entity repository. Then the User service would be passed into the controller.
// UserService
public function getForm($name, $id = null)
{
$form = $this->formRepository->find($name);
if ($id !== null) {
$entity = $this->entityRepository->find($id);
$form->bind($entity);
}
return $form;
}

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.

Resolving multiple services using constructor injection with Windsor in MVC3

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.

Resources