Sometimes I have classes which need to get some information for construction. I am not talking about references to other objects (which will be injected) but about (for instance) strings which are holding unique information:
// Scoped as singleton!
class Repository
{
public Repository( InjectedObject injectedObject, string path ) { ... }
}
How do you get this string injected? One possiblity is to write an Init() method and to avoid injection for the string:
class Repository
{
public Repository( InjectedObject injectedObject ) { ... }
public void Init( string path ) { ... }
}
Another possibility is to wrap the information into an object, which can be injected:
class InjectedRepositoryPath
{
public InjectedRepositoryPath( string path ) { ... }
public string Path { get; private set; }
}
class Repository
{
public Repository( InjectedObject injectedObject, InjectedRepositoryPath path ) { ... }
}
This way I'd have to create an instance of InjectedRepositoryPath during the initialisation of my DI-Container and register this instance. But I need such an unique configuration object for every similar class.
Of course I can resolve a RepositryFactory instead of the Repository object, so the factory would ask me for the path:
class RepositoryFactory
{
Repository Create( string path ) { ... }
}
But again, this is one factory just for a singleton object ...
Or, finally, since the path will be extracted from a configuration file, I could skip passing around the string and read the config in my constructor (which is probably not as optimal, but possible):
class Repository
{
public Repository( InjectedObject injectedObject )
{
// Read the path from app's config
}
}
What's your favorite method? For non-singleton classes you have to use imho the Init() or factory solution, but what about singleton-scoped objects?
If you are using Constructor injection I find adding a parameter which is your configuration object to the constructor is the best way. By using an init function you are somewhat sidestepping the point of constructor injection. This makes testing harder, it also makes maintenance and delivery more difficult.
Discovery becomes a problem because it is not readily apparent that this class requires a configuration object. By adding it to the constructor anyone using this object knows explicitly that this configuration must be there.
I prefer not having a DI Container dictate my API design. The container should conform to proper design, not the other way around.
Design your classes in a DI-friendly manner, but without making concessions to your DI Container. If you need a connection string, then take a string through the constructor:
public class Repository : IRepository
{
public Repository(string path) { //... }
}
Many DI Containers can deal with primitive values. As an example, here's one way to do it with Windsor:
container.Register(Component.For<IRepository>()
.ImplementedBy<Repository>()
.DependsOn( new { path = "myPath" } ));
However, if your container of choice can't deal with primitive parameters, you can always decorate Repository with an implementation that knows how to find the string:
public class ConfiguredRepository : IRepository
{
private readonly Repository decoratedRepository;
public ConfiguredRepository()
{
string path = // get the path from config, or whereever appropriate
this.decoratedRepository = new Repository(path);
}
// Implement the rest of IRepository by
// delegating to this.decoratedRepository
}
Now you can simply tell your container to map IRepository to ConfiguredRepository, while still keeping the core Repository implementation clean.
Related
Need some help trying to solve a problem resolving an implementation of a service at runtime based on a parameter. In other words use a factory pattern with DI.
We have Autofac wired in to our MVC application. I am trying to figure out how we can use a user session variable (Call it Ordering Type) to be used for the Dependency Resolver to resolve the correct implementation of a service.
An example of what we are trying to do.
The application has two "types" of ordering - real eCommerce type of ordering (add stuff to a shopping cart, checkout etc).
The other is called Forecast ordering. Users create orders - but they do not get fulfilled right away. They go through an approval process and then fulfilled.
The bottom line is the data schema and back end systems the application talks to changes based on the order type.
What I want to do is:
I have IOrderManagerService
public interface IOrderManagerService
{
Order GetOrder(int orderNumber);
int CreateOrder(Order order);
}
Because we have two ordering "types" - I have two implementations of the the IOrderManagerService:
public class ShelfOrderManager : IOrderManagerService
{
public Order GetOrder(int orderMumber)
{
...code
}
public int CreateOrder(Order order)
{
...code
}
}
and
public class ForecastOrderManager: IOrderManagerService
{
public Order GetOrder(int orderMumber)
{
...code
}
public int CreateOrder(Order order)
{
...code
}
}
My First question is - in my MVC application - do I register these implementations as?
builder.RegisterType<ShelfOrderManager>().As<IOrderManagerService>();
builder.RegisterType<ForecastOrderManager>().As<IOrderManagerService>();
What we are planning on doing is sticking the user selected ordering type in a users session. When a user wants to view order status - depending on their selected ordering "type" - I need the resolver to give the controller the correct implementation.
public class OrderStatusController : Controller
{
private readonly IOrderManagerService _orderManagerService;
public OrderStatusController(IOrderManagerService orderManagerService)
{
//This needs to be the correct implementation based on the users "type".
_orderManagerService = orderManagerService;
}
public ActionResult GetOrder(int orderNumber)
{
var model = _orderManagerService.GetOrder(orderNumber);
return View(model);
}
}
I've ready about the the delegate factory and this answer explains the concept well.
The problem is the runtime parameters are being used to construct the service and resolve at runtime. i.e.
var service = resolvedServiceClass.Factory("runtime parameter")
All this would do is give me "service" that used the "runtime parameter" in the constructor.
I've looked at Keyed or Named resolution too.
At first I thought I could combine these two techniques - but the controller has the dependency on the interface - not the concrete implementation. (as it should)
Any ideas on how to get around this would be MUCH appreciated.
As it would turn out we were close. #Andrei is on target with what we did. I'll explain the answer below for the next person that comes across this issue.
To recap the problem - I needed to resolve a specific concrete implementation of an interface using Autofac at run time. This is commonly solved by the Factory Pattern - but we already had DI implemented.
The solution was using both. Using the delegate factory Autofac supports, I created a simple factory class.
I elected to resolve the component context privately
DependencyResolver.Current.GetService<IComponentContext>();
versus having Autofac resolve it predominately so I did not have to include IComponentContext in all of my constructors that that will be using the factory.
The factory will be used to resolve the services that are dependent on run time parameters - which means wherever a
ISomeServiceThatHasMultipleImplementations
is used in a constructor - I am going to replace it with ServiceFactory.Factory factory. I did not want to ALSO include IComponentContext wherever I needed the factory.
enum OrderType
{
Shelf,
Forecast
}
public class ServiceFactory : IServiceFactory
{
private readonly IComponentContext _componentContext;
private readonly OrderType _orderType;
public ServiceFactory(OrderType orderingType)
{
_componentContext = DependencyResolver.Current.GetService<IComponentContext>();
_orderType = orderingType;
}
public delegate ServiceFactory Factory(OrderType orderingType);
public T Resolve<T>()
{
if(!_componentContext.IsRegistered<T>())
return _componentContext.ResolveNamed<T>(_orderType.ToString());
return _componentContext.Resolve<T>();
}
}
With the factory written, we also used the Keyed services.
Using my order context -
public interface IOrderManagerService
{
Order GetOrder(int orderNumber);
int CreateOrder(Order order);
}
public class ShelfOrderManager : IOrderManagerService
{
public Order GetOrder(int orderNumber)
{
...
}
public int CreateOrder(Order order)
{
...
}
}
public class ForecastOrderManager : IOrderManagerService
{
public Order GetOrder(int orderNumber)
{
...
}
public int CreateOrder(Order order)
{
...
}
}
The registration of Keyed services:
//register the shelf implementation
builder.RegisterType<ShelfOrderManager>()
.Keyed(OrderType.Shelf)
.As<IOrderManager>();
//register the forecast implementation
builder.RegisterType<ForecastOrderManager>()
.Keyed(OrderType.Shelf)
.As<IOrderManager>();
Register the factory:
builder.RegisterType<IMS.POS.Services.Factory.ServiceFactory>()
.AsSelf()
.SingleInstance();
Finally using it in the controllers (or any other class for that matter):
public class HomeController : BaseController
{
private readonly IContentManagerService _contentManagerService;
private readonly IViewModelService _viewModelService;
private readonly IApplicationSettingService _applicationSettingService;
private readonly IOrderManagerService _orderManagerService;
private readonly IServiceFactory _factory;
public HomeController(ServiceFactory.Factory factory,
IViewModelService viewModelService,
IContentManagerService contentManagerService,
IApplicationSettingService applicationSettingService)
{
//first assign the factory
//We keep the users Ordering Type in session - if the value is not set - default to Shelf ordering
_factory = factory(UIUserSession?.OrderingMode ?? OrderType.Shelf);
//now that I have a factory to get the implementation I need
_orderManagerService = _factory.Resolve<IOrderManagerService>();
//The rest of these are resolved by Autofac
_contentManagerService = contentManagerService;
_viewModelService = viewModelService;
_applicationSettingService = applicationSettingService;
}
}
I want to work out a bit more handling of the Resolve method - but for the first pass this works. A little bit Factory Pattern (where we need it) but still using Autofac to do most of the work.
I would not rely on Autofac for this. IOC is used to resolve a dependency and provide an implementation for it, what you need is to call a different implementation of the same interface based on a decision flag.
I would use a simple factory basically, like a class with 2 static methods and call whichever implementation you need need to when you know what the decision is. This gives you the run-time resolver you are after. Keep it simple I'd say.
This being said it seems there is another option. Have a look at the "select by context" option, maybe you can redesign your classes to take advantage of this: http://docs.autofac.org/en/latest/faq/select-by-context.html
How could I setup my chosen DI for this kind of setup:
public abstract class BaseRepo
{
public BaseRepo(string token)
{
}
}
public RepoA : BaseRepo, IRepoA
{
// implementation of interface here
}
public ViewModelA
{
IRepoA _repo;
public ViewModelA(IRepoA repo)
{
this._repo = repo;
}
public DoMethod()
{
this._repo.DoSomeStuff();
}
}
In real scenario, the token parameter on the base class is resolved after the user has been logged in. I was thinking of just configuring the interfaces for DI after the login but I'm not sure if that a right thing do.
I looked at some Factories but I can't make it to work.
My choice of DI probably goes to AutoFac/Ninject and the project is Xamarin mobile app
In real scenario, the token parameter on the base class is resolved
after the user has been logged in.
This means that the token parameter is runtime data. Prevent injecting runtime data into your components. Your components should be stateless. Instead, runtime data should be passed on through method calls through the previously constructed object graph of components. Failing to do so, will make it much more complicated to configure and verify your object graphs.
There are typically to ways of passing runtime data. Either you pass it on through method calls from method to method through the object graph, or your components call a method that returns that correct value. This token seems like it is contextual information and that would typically mean you choose the latter option:
public interface ITokenProvider {
string GetCurrentToken();
}
// Don't use base classes: base classes are a design smell!
public RepoA : IRepoA
{
private readonly ITokenProvider tokenProvider;
public RepoA(ITokenProvider tokenProvider) {
this.tokenProvider = tokenProvider;
}
// IRepoA methods
public A GetById(Guid id) {
// Get token at runtime
string token = this.tokenProvider.GetCurrentToken();
// Use token here.
}
}
In your Composition Root, you will have to create an implementation for this ITokenProvider. How this implementation looks is highly dependent on how you wish to store this token, but here's a possible implementation:
public sealed class AspNetSessionTokenProvider : ITokenProvider {
public string GetCurrentToken() {
return (string)HttpContext.Current.Session["token"];
}
}
How do I handle classes with static methods with Ninject?
That is, in C# one can not have static methods in an interface, and Ninject works on the basis of using interfaces?
My use case is a class that I would like it to have a static method to create an
unpopulated instance of itself.
EDIT 1
Just to add an example in the TopologyImp class, in the GetRootNodes() method, how would I create some iNode classes to return? Would I construct these with normal code practice or would I somehow use Ninject? But if I use the container to create then haven't I given this library knowledge of the IOC then?
public interface ITopology
{
List<INode> GetRootNodes();
}
public class TopologyImp : ITopology
{
public List<INode> GetRootNodes()
{
List<INode> result = new List<INode>();
// Need code here to create some instances, but how to without knowledge of the container?
// e.g. want to create a few INode instances and add them to the list and then return the list
}
}
public interface INode
{
// Parameters
long Id { get; set; }
string Name { get; set; }
}
class NodeImp : INode
{
public long Id
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public string Name
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
}
// Just background to highlight the fact I'm using Ninject fine to inject ITopology
public partial class Form1 : Form
{
private ITopology _top;
public Form1()
{
IKernel kernal = new StandardKernel(new TopologyModule());
_top = kernal.Get<ITopology>();
InitializeComponent();
}
}
If you're building a singleton or something of that nature and trying to inject dependencies, typically you instead write your code as a normal class, without trying to put in lots of (probably incorrect) code managing the singleton and instead register the object InSingletonScope (v2 - you didnt mention your Ninject version). Each time you do that, you have one less class that doesnt surface its dependencies.
If you're feeling especially bloody-minded and are certain that you want to go against that general flow, the main tools Ninject gives you is Kernel.Inject, which one can use after you (or someone else) has newd up an instance to inject the dependencies. But then to locate one's Kernelm you're typically going to be using a Service Locator, which is likely to cause as much of a mess as it is likely to solve.
EDIT: Thanks for following up - I see what you're after. Here's a hacky way to approximate the autofac automatic factory mechanism :-
/// <summary>
/// Ugly example of a not-very-automatic factory in Ninject
/// </summary>
class AutomaticFactoriesInNinject
{
class Node
{
}
class NodeFactory
{
public NodeFactory( Func<Node> createNode )
{
_createNode = createNode;
}
Func<Node> _createNode;
public Node GenerateTree()
{
return _createNode();
}
}
internal class Module : NinjectModule
{
public override void Load()
{
Bind<Func<Node>>().ToMethod( context => () => Kernel.Get<Node>() );
}
}
[Fact]
public void CanGenerate()
{
var kernel = new StandardKernel( new Module() );
var result = kernel.Get<NodeFactory>().GenerateTree();
Assert.IsType<Node>( result );
}
}
The ToMethod stuff is a specific application of the ToProvider pattern -- here's how you'd do the same thing via that route:-
...
class NodeProvider : IProvider
{
public Type Type
{
get { return typeof(Node); }
}
public object Create( IContext context )
{
return context.Kernel.Get<Node>();
}
}
internal class Module : NinjectModule
{
public override void Load()
{
Bind<Func<Node>>().ToProvider<NodeProvider>();
}
}
...
I have not thought this through though and am not recommending this as A Good Idea - there may be far better ways of structuring something like this. #Mark Seemann? :P
I believe Unity and MEF also support things in this direction (keywords: automatic factory, Func)
EDIT 2: Shorter syntax if you're willing to use container-specific attributes and drop to property injection (even if Ninject allows you to override the specific attributes, I much prefer constructor injection):
class NodeFactory
{
[Inject]
public Func<Node> NodeFactory { private get; set; }
public Node GenerateTree()
{
return NodeFactory();
}
}
EDIT 3: You also need to be aware of this Ninject Module by #Remo Gloor which is slated to be in the 2.4 release
EDIT 4: Also overlapping, but not directly relevant is the fact that in Ninject, you can request an IKernel in your ctor/properties and have that injected (but that doesn't work directly in a static method).
I have a structuremap configuration that has me scratching my head. I have a concrete class that requires a interfaced ui element which requires an interfaced validation class. I want the outer concrete class to get the default ui element, but get a concrete-class-specific validation object. Something like this:
class MyView
{
IPrompt prompt
}
class GenericPrompt : IPrompt
{
IValidator validator
}
class MyValidator : IValidator
{
bool Validate() {}
}
How can I configure structuremap with the Registry DSL to only use MyValidator when creating dependencies for MyView. (And assumedly using BobsValidator when creating dependencies for BobsView)
Are you getting MyView (and BobsView) from the container? Can we assume that they will all take an instance of IPrompt?
One approach would be to register all of your validators with a name that matches the names of your view. You could implement your own type scanner that just removes the Validator suffix:
public class ValidatorScanner : ITypeScanner
{
public void Process(Type type, PluginGraph graph)
{
if (!typeof (IValidator).IsAssignableFrom(type)) return;
var validatorName = type.Name.Replace("Validator", "");
graph.AddType(typeof(IValidator), type, validatorName);
}
}
Now, if you assume an IPrompt will always be requested by a View that follows that naming convention, your registry could look like:
public class ValidatorRegistry : Registry
{
public ValidatorRegistry()
{
Scan(scan =>
{
scan.TheCallingAssembly();
scan.With<ValidatorScanner>();
});
ForRequestedType<IPrompt>().TheDefault.Is.ConstructedBy(ctx =>
{
var viewName = ctx.Root.RequestedType.Name.Replace("View", "");
ctx.RegisterDefault(typeof(IValidator), ctx.GetInstance<IValidator>(viewName));
return ctx.GetInstance<GenericPrompt>();
});
}
}
To retrieve your view with the appropriate validator, you would have to request the concrete type:
var view = container.GetInstance<MyView>();
Note that this will only work if you are retrieving your view with a direct call to the container (service location), since it depends on the "Root.RequestedType". Depending on how you plan to get your views, you might be able to walk up the BuildStack looking for a View (instead of assuming it is always Root).
I am using windsor castle as my IoC container, and has run in to a bit of a problem. This is best explained in code, so I´ll give it a try.
I have a factory class, that should provide me with implementations of a certain interface:
public interface IObjectCreatorFactory
{
IObjectCreator GetObjectCreator(Type objectType);
}
public interface IObjectCreator
{
T CreateObject<T>(IDataRow data);
bool SupportsType(Type type);
}
Implementation of the factory class could look like this, though I am not sure this is the way to go:
public interface ObjectCreatorFactory:IObjectCreatorFactory
{
IEnumerable specificCreators;
IObjectCreator defaultCreator;
public ObjectCreatorFactory(IEnumerable<IObjectCreator> specificCreators, IObjectCreator defaultCreator)
{
this.specificCreators= specificCreators;
this.defaultCreator= defaultCreator;
}
public IObjectCreator GetObjectCreator(Type objectType)
{
foreach (IObjectCreator creator in specificCreators)
{
if (creator.SupportsType(objectType))
{
return creator;
}
}
return defaultCreator;
}
}
Now this would work out ok, but if I want my IObjectCreator instance to create child objects using a specific IObjectCreator, i would like to call ObjectCreatorFactory, and this obviously results in a circular reference:
public void SpecificObjectCreator:IObjectCreator
{
IObjectCreatorFactory objCreatorFactory;
public SpecificObjectCreator(IObjectCreatorFactory objCreatorFactory)
{
this.objCreatorFactory = objCreatorFactory;
}
T CreateObject<T>(IDataRow data)
{
T obj = new T;
ChildObject childObject = objCreatorFactory.GetObjectCreator(typeof(ChildObject)).CreateObject<ChildObject>(data);
.......
}
bool SupportsType(Type type);
}
This does not work out. What would be the way to go for this scenario, where the created objects are refering back to the factory for child object creators?
I would simply move the factory out of the constructors of the various specific object creators, and introduce a method on the IObjectCreator interface instead, responsible for initialising the creators:
public interface IObjectCreator
{
T CreateObject<T>(IDataRow data);
bool SupportsType(Type type);
void Initialize(IObjectCreatorFactory factory);
}
And then just invoke Initialze(this) on each object creator passed into the factory.
In the past I've used custom life cycle stages to take care of automatically invoking "post-construction" setup of components to both avoid circular dependencies and also to take care of other associated concerns (i.e. applying additional component configuration from an external source like a database) - but it's probably overkill for what you need.