I have a IFileSystemService interface, which defines a set of file & directory management functions. It has an implementation and is injected by Autofac into controllers that need it.
However, for reasons out of our control, we now have a requirement to move one specific part of the website to use database instead of the filesystem, while maintaining the same functionality (i.e., a "lite" version of a filesystem using database for storage). For this, I have created a second implementation of IFileSystemService, which works with the DB instead of the actual filesystem.
However, I can't figure out how to tell Autofac to use this second implementation on the specific controller(s) that need it, while leaving the original implementation as the default for all others.
Services can be "named" in AutoFac as per https://code.google.com/p/autofac/wiki/TypedNamedAndKeyedServices
To register the Db implementation of the IFileSystemService as a named instance:
builder.Register<MyDbFileSystemService>().Named<IFileSystemService>("DbFileSystemService");
Then to get the dependent controller to use the named registration:
builder.Register(c => new MyControllerWithDbDependency(c.Resolve< IFileSystemService >("DbFileSystemService")))
.As<Controller>()
.etc
In the case of the updated question when this is not feasible due to the large number of additional dependencies, I would do one of the following:
Move the IFileSystemService dependency into a property of the controller
Abstract the resolution of the IFileSystemService into a factory and dynamically resolve the dependency at runtime
Register the concrete IFileSystemService implementations as services for their own specific types and then use specific implementations within the signature of the controller constructor
IFileSystemService Factory
public class MyControllerWithDbDependency : Controller
{
MyControllerWithDbDependency(IFileSystemServiceFactory fileSystemServiceFactory,
ISomeOtherDependency ...)
{
_service = fileSystemServiceFactory.Create("MyDbFileSystemServiceFactory");
}
}
public interface IFileSystemServiceFactory
{
IFileSystemServiceFactory Create(string dependencyName);
}
public class AutoFacFileSystemServiceFactory : IFileSystemService
{
private readonly IComponentContext _componentContext;
public AutoFacFileSystemServiceFactory(IComponentContext componentContext)
{
if (componentContext == null) throw new ArgumentNullException("componentContext");
_componentContext = componentContext;
}
public IFileSystemService Create(string dependencyName)
{
return _componentContext.ResolveNamed<IFileSystemService>(dependencyName);
}
}
I.e. each controller is responsible for specifying the specific IFileSystemService dependency it requires, which in turn means no alteration to the AutoFac configuration for the controllers.
To be honest, I usually only use this technique in situations where the specific type to be resolved is genuinely not known until runtime - unlike in the case of the question where it would be used as a workaround.
Obviously if you have a large number of controllers and a small set of IFileSystemService implementations, and if it makes sense from a design perspective, you could push the call to Create on the factory to a custom controller base type and save yourself some code duplication.
Register specific implementations of IFileSystemService as services of themselves
public class MyControllerWithDbDependency : Controller
{
MyControllerWithDbDependency(MyDbFileSystemService dbFileSystemService,
ISomeOtherDependency ...)
{
// ...
}
}
// AutoFac configuration
builder.RegisterType<MyDbFileSystemService>()
.As<MyDbFileSystemService>()
.InstancePerWhatever();
builder.RegisterType<DefaultFileSystemService>()
.As<IFileSystemService>()
.InstancePerWhatever();
Related
I'm using a custom JsonConverter and JsonSerializerSettings.TypeNameHandling = TypeNameHandling.Objects to create the required instances during deserialization. The instances are created by resolving the types from an Autofac IOC container. Everything works fine, except...
I have several "core objects" that request a unique Id in the constructor from a service (which is correctly injected into the constructor). When deserializing this should not happen because it is fairly expensive and the Ids will be populated from the Json file anyway once the instance has been created.
Currently, when resolving from within the custom JsonConverter I'm using _scope.Resolve<T>(new TypedParameter(typeof(IIdService), null)); to then - in the called constructor - check for null and act accordingly.
Some people apparently consider multiple constructors worse than a code-smell when using an IOC (which makes me wonder why Autofac offers several features regarding the topic), but in the context of deserialization I think it can make perfect sense.
As far as I can tell Autofac has mechanisms to decide which constructor to use during registration, but not when resolving. My preferred solution would be to add a custom attribute to a constructor (e.g. [CtorForDeserializing]) and use that for deciding. Is that possible?
There are a couple of extension points Autofac has for reflection-based activations but doesn't have well documented yet that may help you out: IConstructorFinder and IConstructorSelector.
IConstructorFinder is used to locate all the available constructors on a type. The core example is the DefaultConstructorFinder which locates only public constructors. If you wanted to, say, hide constructors with particular attributes or start finding internal/private constructors, you could create a custom finder. This really only happens once so you don't get to make runtime choices here.
IConstructorSelector is used to choose, at resolve time, which constructor should be used to instantiate the object. There are a couple of these in core Autofac, but the primary example is the MostParametersConstructorSelector which selects the constructor that has the most available matching parameters at the time. Constructors get found by the IConstructorFinder and then that set of constructors is what is presented to the IConstructorSelector to choose from. This is where you could make more runtime choices since it happens every time the object is resolved.
There are extension methods to help you add your finder/selector to a registration:
builder.RegisterType<MyType>()
.FindConstructorsWith(new MyConstructorFinder())
.UsingConstructor(new MyConstructorSelector());
You don't have to customize both things, you can just do one or the other if you want. I'm just showing you the extensions.
Actually Autofac is able to decide which constructor to use both ways - during registration or resolution. For resolution part here is the quote from documentation: "Autofac automatically uses the constructor for your class with the most parameters that are able to be obtained from the container" (see here).
Consider following example.
public interface ISomeService
{
Guid Id { get; }
}
public class SomeService : ISomeService
{
public Guid Id { get; }
public SomeService()
{
Id = Guid.NewGuid();
}
public SomeService(Guid id)
{
Id = id;
}
}
// Startup.cs:
builder.RegisterType<SomeService>().As<ISomeService>().InstancePerLifetimeScope();
// TestController.cs:
[Route("api/[controller]")]
public class TestController : Controller
{
private readonly IComponentContext _context;
public TestController(IComponentContext context)
{
_context = context;
}
[HttpGet]
public IActionResult Get()
{
var service = _context.Resolve<ISomeService>();
return Ok(service.Id);
}
[HttpGet("{id}")]
public IActionResult Get(Guid id)
{
var service = _context.Resolve<ISomeService>(new NamedParameter("id", id));
return Ok(service.Id);
}
}
// GET http://localhost:5000/api/test/e0198f72-6337-4880-b608-68935122cdea
// each and every response will be the same: e0198f72-6337-4880-b608-68935122cdea
// GET http://localhost:5000/api/test
// this way it responds with some random guid each time endpoint is called
Travis Illig sent me in the right direction - thanks!
I ended up implementing a solution around the following details:
Implement custom attributes, e.g.: public class DeserializeCtorAttribute : Attribute { }, which will be used by the (also to be implemented) IConstructorFinder.
Implement an empty generic interface, e.g.: IDeserializable<T>, which will be used for resolving the services/components.
Let relevant component classes implement the interface (MyClass : IDeserializable<MyClass>) and add an extra registration for the component:
_builder.RegisterType<MyClass>().As<IDeserializable<MyClass>>()
.FindConstructorsWith(MyConstructorFinder);
Use the implemented DeserializeCtorAttribute in the desired constructor of MyClass.
Let the JsonConverter create the required instance by calling (MyClass) scope.Resolve(IDeserializable<MyClass>); casting is required, but safe. Due to the registration the instance will be created using the desired constructor.
I am using autofac in my UWP application.
I am using the facade pattern for my backend and it is represented by an IFacade interface.
public interface IFacade
{
/* forwards view-models' calls to different parts of the backend */
}
The view-models of my UWP application are using an implementation of IFacade whose concrete implementation is resolved through autofac in the UWP's App instance.
public class App : Application
{
...
private IFacade InitializeDependencies()
{
var containerBuilder = new ContainerBuilder();
// Registers all the platform-specific implementations of services.
containerBuilder.RegisterType<LoggingService>().As<ILoggingService>().SingleInstance();
containerBuilder.RegisterType<SQLitePlatformService>().As<ISQLitePlatformService>().SingleInstance();
containerBuilder.RegisterType<DiskStorageService>().As<IDiskStorageService>().SingleInstance();
containerBuilder.RegisterType<IdentityProviderFactoryService>().As<IIdentityProviderFactoryService>().SingleInstance();
containerBuilder.RegisterType<DefaultVaultService>().As<IVaultService>().SingleInstance();
containerBuilder.RegisterType<LocationService>().As<ILocationService>().SingleInstance();
containerBuilder.RegisterType<NavigationService>().As<INavigationService>().SingleInstance();
// Registers all the dependencies of the Backend project.
var backendDependencies = new Dependencies();
backendDependencies.Setup(containerBuilder);
// Resolves the IFacade.
var container = containerBuilder.Build();
var lifetimeScope = container.BeginLifetimeScope();
return backendDependencies.ResolveFacade(lifetimeScope);
}
I have a lot of services in my backend and my implementation of IFacade ends up with that horrific constructor referencing a lot of services' interfaces, something would make Uncle Bob cringe.
internal sealed Facade : IFacade
{
public Facade(ISessionService sessionService, IEntitiesRepository entitiesRepository, ISynchronizationService synchronizationService, IVaultService vaultService, IIdentityProviderFactoryService identityProviderFactoryService, IDemoTapeService demoTapeService, IDiskStorageService diskStorageService)
{
/* Saves the references as read-only fields. */
}
}
Question
Contrary to the ServiceLocator, using DI forces us to make all the dependencies that are needed visible. I am not sure if I am using the Dependency Injection properly.
What can I do so that my constructor of my Facade class does not have that many parameters?
Solutions tried
Properties
I could change the Facade class and inject the services through public properties. I am not fond of lots of public get / set as my IFacade contract would now indicate that those properties could be changed after the Facade implementation is created, which is not something I want to support (and debug).
Aggregate interfaces
Another option would be to aggregate interfaces together (something that I call the SomethingContext classes) but then it is harder to understand what these groups of interfaces would mean.
Inject a ServiceLocator that is not static in the Facade constructor
The last solution that seems more acceptable (well... acceptable to me) would be to use DI to inject a non-static ServiceLocator. It is kind of solution 2). However, I know the ServiceLocator is something that is frowned upon.
So one another approach is to create some smaller Facade Services and then inject those services to the main facade.
For example you can create such smaller facade for INavigationService and ILocationService:
public class GeographyService : IGeographyService
{
public GeographyService(
INavigationService navigationService,
ILocationService locationService)
{
}
}
The same is true for ISQLitePlatformService and DiskStorageService:
public class StorageService : IStorageService
{
public StorageService(
ISQLitePlatformService databaseService,
DiskStorageService diskStorageService)
{
}
}
That's of course only an example of an idea.
Such an approach is generally considered better than aggregate services with all the dependencies aggregated (http://autofaccn.readthedocs.io/en/latest/advanced/aggregate-services.html) or ServiceLocator (anti-)pattern. You can also read some thoughts about it here: http://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices/
In the MVC application i am working with these days, they have registered and resolved all the Interface/Concrete class dependencies inside the controller itself. I read about ioc and dependency inversion and found that the thing that has been done is completely non-useful. Since it would anyway not allow the application to leverage benefits of IoC example mocking, unit testing and would also add cost of adding/resolving the dependencies unnecessarily. Below is code sample:
HomeController
using(IUnityContainer container= new UnityContainer())
{
container.RegisterType<IRepository1, Repository1>()
IRepository1 _repos1 = container.Resolve<IRepository1>();
}
I dont see any point of doing all this stuff if we dont get any benefit out of this. Can someone please tell if this could be of any use now or in future?
If not, i am planning to simply instantiate them with concrete implementations or like:
IRepository1 repos1= new Repository1();
Please ignore the syntax.
(I have editted the code snippet now.)
Using a container to first register and then resolve a concrete type doesn't make any sense, there is no benefit of that. You are still coupled to a concrete type. You could possibly argue that the container helps to match all constructor parameters with instances of respective types but this doesn't count as a real benefit in my opinion.
If you really don't plan to make use of abstractions that are resolved externally, then yes, you can safely remove the bloating container code and create concrete instances, just as you have presented.
The immediate answer to this question is your current implementation causes more overhead and performance impact then doing a standard construction, and you should remove it; or redesign your implementation of Unity.
The following is an example of the benefit of injection that occurs when resolving to a type that has a dependency of another type that is registered with the unity container.
public class UserService
{
internal readonly IRepository _repository;
public UserService(IRepository repository)
{
_repository = repository;
}
//Service Method that exposes 'Domain Logic'
public void CreateUser(string FirstName)
{
_repository.Insert<User>(new User() { FirstName = FirstName }); //Assumes there is a Generic method, Insert<T>, that attaches instances to the underline context.
}
public User GetUser(string FirstName)
{
return _repository.Query<User>().FirstOrDefault(user => user.FirstName == FirstName); // assumes there is a Generic method, Query<T>, that returns IQueryable<T> on IRepository
}
}
register the types (probably in a singleton pattern at Global.asax)
//Resolver is an instance of UnityContainer
Resolver.RegisterType<IRepository, Repository>(new ContainerControlledLifetimeManager());
Resolver.RegisterType<IUserService, UserService>();
Then the logic in your controller is like so:
var service = Resolver.Resolve<IUserService>(); //the resolver will resolve IRepository to an instance as well...
var user = service.GetUser("Grant");
Let's suppose I have two different concrete classes that both implement the same interface:
public interface IDataSource{
Connection CreateConnection();
}
public class DataSourceA: IDataSource
{
....
}
public class DataSourceB: IDataSource
{
....
}
Now I want to register both of these with my unity container:
var container = new UnityContainer();
container.RegisterType<IDataSource, DataSourceA>("A");
container.RegisterType<IDataSource, DataSourceB>("B");
I know that I can specify the mapping name when I resolve a dependency :
var myDataSource = conatiner.Resolve<IDataSource>("A");
However, in my case, I won't be resolving the dependency myself. I am creating many different controllers and I will be using UnityDependencyResolver (from ASP.Net MCVC) to create all the controllers. Some of my controllers required DataSource A, some require DataSource B, and some require both. What I'd like to do is specify which one to use as an attribute on the constructor parameter, like this:
public class ReportController{
public ReportController([InjectionQualifier("A")] IDataSource dataSource)
{
...
}
}
Is something like that possible? I come from the spring world in java and I would use an #Qualifier annotation in this case using that stack.
The attribute you are looking for is
[Dependency("A")]
With Unity how do I inject a named dependency into a constructor?
I personally don't like using the Dependency Attribute because you're directly depending on the Unity library. You might as well pass in the IUnityContainer in your constructor.
Usually when you need to use named dependencies, it's because you are trying to implement some kind of strategy pattern.
What I do is that I isolate Unity in a class called StrategyResolver and inject the StrategyResolver as dependency. Since the StrategyResolver belongs to me then my "services" classes no longer have any hard dependencies on any Unity library objects except inside the StrategyResolver but that's acceptable since I will never have to modify the StrategyResolver ever again when adding new strategies in the future.
Take a look, I've detailed my approach in this answer with code examples : https://stackoverflow.com/a/37882179/483638
I am building an application which uses an Abstract Factory pattern to allow runtime determination of which subclass of my IHardwareDevice to create based upon how it responds to a request for identification. I might create Hardware1 or Hardware2.
The problem arises in that I want to use a State pattern in these IHardwareDevice objects and I want to have the State be created by the IoC container. Is there a good way to do this without directly calling the IoC container to resolve the State objects with which to hydrate the IHardwareDevice?
Or, am I thinking about this in the wrong way? Because my Factory is pretty much the entry point into this library, is it okay to have this Factory handle instantiating the container for use in the library? I was planning on having the client application instantiate the container and then use it to gain access to which ever parts of the library it requires, such as the Factory.
I am planning to use Windsor as the IoC container, but am at an early enough stage in the project to switch if needed.
Here's one way it can be done with Autofac 2.2 (http://autofac.org):
First, an enum to discriminate between states (making up some likely values):
public enum DeviceState { Online, Offline }
Then, the state implementations, like:
public class OnlineState : IDeviceState { }
Next, register each state with its corresponding enum key:
var builder = new ContainerBuilder();
builder.RegisterType<OnlineState>().Keyed<IDeviceState>(DeviceState.Online);
builder.RegisterType<OfflineState>().Keyed<IDeviceState>(DeviceState.Offline);
// Register other components here
Finally, the hardware device uses an index to choose states. The implementation of IIndex is provided automatically by the container:
public class Modem : IHardwareDevice
{
IIndex<DeviceState, IDeviceState> _states;
IDeviceState _currentState;
public Modem(IIndex<DeviceState, IDeviceState> states)
{
_states = states;
SwitchOn();
}
void SwitchOn()
{
_currentState = _states[DeviceState.Online];
}
}
Hope this helps.
Nick
Most IoC containers, including Windsor, has the option to pass explicit dependencies (parameters) to the constructors of the resolved dependencies; when you call the Resolve method.
So yes, you can pass your State object explicitly to the IHardwareDevice instance you are resolving.
Windsor has a very powerful facility for auto-implementing abstract factories - Typed Factory Facility
It is largely convention based, and if the default convention does not suit your needs, you can override it by providing custom ITypedFactoryComponentSelector.
It gives you access to all information you may need to make the decision - what inline arguments you want to pass down the invocation lane, and what component you want to resolve.