My factory is using method injection because I thought this was the best way to make it so far. Besides, I doubt it is a good thing after having to call on its Create method from within a dependent object.
The only way I might think of whilst continuing to use the parameterized factory Create method, is to inject the dependencies directly in the MainPresenter so that it may provide with the dependencies to the method, and I dislike it. It dislike it because it is not the MainPresenter that depends on the ICustomerManagementView and the ICustomerDetailPresenterFactory, it's its dependency. So I would feel like I'm sabotaging my own code by doing so.
MainPresenter
public class MainPresenter : Presenter<IMainView>, IMainViewUiHandler {
public MainPresenter(IMainView view
, ICustomerManagementPresenterFactory customerManagementFactory)
: base(view) {
this.customerManagementPresenterFactory = customerManagementPresenterFactory;
}
public void ManageCustomers() {
// The following line is causing trouble.
// As you can see per the ICustomerManagementPresenterFactory code sample,
// the Create() method takes two parameters:
// 1. ICustomerManagementView, and
// 2. ICustomerDetailPresenterFactory
// Hence I have to provide the dependencies manually, I guess. Which is
// something to avoid at any cost.
var customerManagementPresenter = customerManagementPresenterFactory.Create();
customerManagementPresenter.ShowView();
}
}
ICustomerManagementPresenterFactory
public interface ICustomerManagementPresenterFactory {
// Here. Though I ask Ninject to inject my dependencies, I need to
// provide values to the parameters when calling the method from within
// the MainPresenter class. The compiler won't let me do otherwise! And
// this makes sense!...
[Inject]
CustomerManagementPresenter Create(ICustomerManagementView view
, ICustomerDetailPresenterFactory factory);
}
IMainView
public interface IMainView : IView, IHasUiHandler<IMainViewUiHandler> {
}
IMainViewUiHandler
public interface IMainViewUiHandler : IUiHandler {
void ManageCustomers();
}
IUiHandler
public interface IUiHandler {
}
IHasUiHandler
public interface IHasUiHandler<H> where H : IUiHandler {
H Handler { set; }
}
MainForm
public partial class MainForm : Form, IMainView {
public MainForm() { InitializeComponent(); }
public IMainViewUiHandler Handler { private get { return handler; } set { setHandler(value); } }
}
CompositionRoot
public class CompositionRoot {
private CompositionRoot() { }
public static IKernel BuildObjectGraph() {
IKernel kernel = new StandardKernel();
BindFactories(kernel);
BindViews(kernel);
}
private static void BindFactories(IKernel kernel) {
kernel.Bind(services => services
.From(AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => !a.FullName.Contains("Tests")))
.SelectAllInterfaces()
.EndingWith("Factory")
.BindToFactory()
);
}
private static void BindViews(IKernel kernel) {
kernel.Bind(services => services
.From(AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => a.FullName.Contains("Windows")
&& !a.FullName.Contains("Tests"))
.SelectAllClasses()
.EndingWith("Form")
.BindSelection((type, baseType) => type
.GetInterfaces()
.Where(iface => iface.Name.EndsWith("View"))
)
);
}
}
So I wonder, is it best to implement the ICustomerManagementPresenterFactory and bind the implementer with it within my CompositionRoot, so that I could provide those dependencies through constructor injection to the Create method which shall no longer take any arguments, or shall I make it otherwise?
What I like of writing a simple interface is that Ninject does it all for me to a factory, and no code is necessary to build an instance of the desired type. Besides, when the constructor of the class to be created uses constructor injection, it seems like it is impossible to have a simple factory interface bound as a factory, and one need to implement the factory interface by hand.
What did I get right/wrong?
As a matter of fact you don't need to pass parameters to the factory Create method at all - except in case they are parameters which need to be passed "down" because they cannot be bound in the composition root (for example an input value). However, passing such parameters to constructors is usually a code smell. Mostly, it's a better idea to pass these parameters to methods instead of constructors (for example: Adder.Add(5,3);, not new Adder(5, 3).ComputeResult();.
Now consider the following example, which works perfectly fine:
public class Dependency1 { }
public interface IDependency2 { }
public class Dependency2 : IDependency2 { }
public interface IBar { }
public class Bar : IBar
{
public Bar(Dependency1 d1, IDependency2 d2) { }
}
public interface IBarFactory
{
IBar Create();
}
var kernel = new StandardKernel();
kernel.Bind<IBarFactory>().ToFactory();
kernel.Bind<IBar>().To<Bar>();
kernel.Bind<Dependency1>().ToSelf();
kernel.Bind<IDependency2>().To<Dependency2>();
var factory = kernel.Get<IBarFactory>();
var bar = factory.Create();
bar.Should().BeOfType<Bar>();
even though Bar takes two constructor arguments, the generated IBarFactory's Create() method does not specify so. No problem, ninject will resolve it automatically.
Now let me give you an example what .ToFactory() actually results in. Consider the factory:
public interface ISomeFactory
{
ISomething Create(string parameter1);
}
Will result in (remark: it's realised by interceptors and not by weaving it, so the example is a simplificiation):
public class SomeFactory : ISomeFactory
{
private readonly IResolutionRoot resolutionRoot;
public SomeFactory(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public ISomething Create(string parameter1)
{
this.resolutionRoot.Get<ISomething>(new ConstructorArgument("parameter1", parameter1);
}
}
The ConstructorArgument tells ninject to pass the value of parameter1 to the ctor-parameter named "parameter".
All other parameters are resolved "as usual". If a constructor parameter cannot be resolved (neither passed as parameter nor bound) ninject will throw an exception stating that the parameter cannot be resolved.
Related
In a .NET Core 3.1 console application I want a Class that would have some parameters in constructor injected but some that I could assign manually. For example something like that but with IConfiguration Injected:
static void Main() {
var myObj1 = new MyClass(1);
var myObj2 = new MyClass(2);
}
public class MyClass {
public MyClass(IConfiguraiton config, int myVal)
{
}
}
I tried this with Ninject:
static void Main()
{
kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Get<MyClass>();
}
public class MyClass
{
public MyClass(IConfiguraiton config)
{
}
}
public class Bindings : NinjectModule
{
public override void Load()
{
var configuration = new ConfigurationBuilder().AddJsonFile($"appsettings.json").Build();
Bind<IConfiguration>().ToMethod(ctx => SetupConfiguration()).InSingletonScope();
Bind<MyClass>().ToSelf().InTransientScope();
}
}
I managed to make simple dependency injection, but haven't had any success making injection with parameters.
I've read a lot of people suggesting that it's better to pass parameters into methods of the class rather than constructor, however in my situation this isn't an option in addition I'm a software engineering student, and would like to learn how to do this, since it might be useful in some situations.
This is a situation where the Ninject.Extensions.Factory is useful, as it is made exactly for this situation. It does pull in the Factory dependency in addition to Castle.Core, as it uses DynamicProxy under the hood (as a SE student, playing with this library is a good idea for using the interceptor pattern).
To use it, you define a Factory interface like so:
public interface IMyClassFactory
{
MyClass Create(int myVal);
}
Note that the Create method returns MyClass, and the argument(s) to the Create method match exactly in type and name to the arguments you wish to provide. The argument type(s) you want injected must be registered with the kernel. Unfortunately, it is easy to make a mistake here - if you specify a parameter that does not exist in the factory interface it is ignored, but if you forget one it will throw an exception when called.
Next, register IMyClassFactory like this: Bind<IMyClassFactory>().ToFactory(); and remove your binding for MyClass. Then wherever you need to create an instance, inject IMyClassFactory and call Create: kernel.Get<IMyClassFactory>().Create(2)
You can achieve the same result without using Ninject.Extensions.Factory by writing and registering your own implementation of IMyClassFactory, essentially doing the same thing that the code the Factory extension ends up emitting. A full sample is below using both methods based on commenting in/out the registration (note the output if you add .InSingletonScope() to the registration of IConfiguraiton - both approaches respect the binding scopes of Ninject).
internal class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel();
kernel.Bind<IConfiguraiton>().To<Configuraiton>();
kernel.Bind<IMyClassFactory>().ToFactory();
//kernel.Bind<IMyClassFactory>().To<NinjectMyClassFactory>().InSingletonScope();
var factory = kernel.Get<IMyClassFactory>();
var one = factory.Create(1);
var two = factory.Create(2);
}
}
public interface IMyClassFactory
{
MyClass Create(int myVal);
}
public class NinjectMyClassFactory : IMyClassFactory
{
public NinjectMyClassFactory(IResolutionRoot resolutionRoot)
{
ResolutionRoot = resolutionRoot;
}
private IResolutionRoot ResolutionRoot { get; }
public MyClass Create(int myVal)
{
return ResolutionRoot.Get<MyClass>(new ConstructorArgument("myVal", myVal));
}
}
public class MyClass
{
public MyClass(IConfiguraiton config, int myVal)
{
Console.Out.WriteLine("Created MyClass({0},{1})", config.MyNum, myVal);
}
}
public interface IConfiguraiton { int MyNum { get; } }
public class Configuraiton : IConfiguraiton
{
static int CreateCount;
public Configuraiton()
{
MyNum = Interlocked.Increment(ref CreateCount);
}
public int MyNum { get; }
}
In my implementation, I need to dynamically resolve a service, based on the servicekey. Therefor, I want to pass a Func, but can't get that working. Any help on this is appreciated.
Let's have the following implemention:
public interface IMyInterface {
void Foo();
}
public class ClassA : IMyInterface {
void Foo() => BarA();
}
public class ClassB : IMyInterface {
void Foo() => BarB();
}
public class ClassC : IOtherInterface {
private readonly Func<string, IMyInterface> getInstance_;
void ClassC(Func<string, IMyInterface> getInstance)
{
getInstance_ = getInstance;
}
void SomeLogic()
{
IMyInterface implementation = getInstance("keyA");
implementation.Foo();
}
}
public static void Main()
{
var c = new Container();
c.Register<IMyInterface, ClassA>(serviceKey:"keyA");
c.Register<IMyInterface, ClassB>(serviceKey:"keyB");
c.Register<IOtherInterface, ClassC>();
c.Resolve<IOtherInterface>();
}
The last call fails, which I understand. The exception thrown is:
DryIoc.ContainerException: 'Unable to resolve IMyInterface with passed arguments [_String0] IsWrappedInFunc, IsDirectlyWrappedInFunc
in wrapper Func<String, IMyInterface> FactoryId=10 with passed arguments [_String0] IsResolutionCall
from Container with Scope {no name}
with Rules with {TrackingDisposableTransients} and without {ThrowOnRegisteringDisposableTransient}
with normal and dynamic registrations:
("keyA", {FactoryID=32, ImplType=ClassA}) ("keyB", {FactoryID=33, ImplType=ClassB}) '
I figured out how to register this with a Delegate:
c.RegisterDelegate<Func<string, IMyInterface>>(r => (key) => c.Resolve<IMyInterface>(key));
But in the documentation, DryIoc recommends using factory-methods above Delegates.
I've played a lot with Made.Of-notations (which I find poorly documented), but have not found a working one.
Is this possible with a (static) Factory-method?
If you need to dynamically select the service based on the key but without relying on Service Locator anti-pattern (without injecting the IResolver into ClassC) -
you may inject all available service factories as described here https://github.com/dadhi/DryIoc/blob/master/docs/DryIoc.Docs/RegisterResolve.md#keyed-registrations in the second example:
public class ClassC : IOtherInterface {
private readonly Func<string, IMyInterface> _implementations;
void ClassC(KeyValuePair<string, Func<IMyInterface>>[] implementations)
{
_implementations = implementations;
}
void SomeLogic()
{
var implementationFactory = _implementations.First(x => x.Key == "keyA").Value;
var implementation = implementationFactory();
implementation.Foo();
}
}
BTW, The same approach is taken in Autofac and maybe by other DI containers capable to compose the wrappers like Func, Lazy and the collections.
BTW2, If you don't like the KeyValuePair you may use Tuple instead.
These days I'm facing this situation often and I'm looking for an elegant solution. I have :
public abstract class TypeA
{
public abstract void AbtractMethod(IDependency dependency);
}
public class TypeB : TypeA
{
public override void AbtractMethod(ISpecializedDependencyForB dependency) { }
}
public class TypeC : TypeA
{
public override void AbtractMethod(ISpecializedDependencyForC dependency) { }
}
public interface IDependency { }
public interface ISpecializedDependencyForB : IDependency { }
public interface ISpecializedDependencyForC : IDependency { }
My objective is to make things transparent in the client perspective and to consume this code like that :
TypeA myDomainObject = database.TypeARepository.GetById(id); // The important point here is that I don't know if the object is of TypeB or TypeC when I consume it.
IDependency dependency = ? // How do I get the right dependency
myDomainObject.AbtractMethod(dependency);
So the thing is that since I don't know the concrete type of the object, I can't inject the right dependency into it.
What I'm currently doing is that I create an abstract factory, to inject the right properties. I have two problems with that, the first one is that I would end up with a lot of factories. The second one is that it makes polymorphism useless since the client actually needs to care about "managing" the underlying type (I need to inject all the possible dependencies in the factory, and to instantiate the factory on the client code).
1) Therefore I was thinking of using property injection with unity, but I can't find out if it's possible to resolve the dependencies of an object, after it's been instanciated manually. Even with this approach I think I could still meet the same problem : I'm not sure if unity would check the actual type of the object and resolve the right dependency if a syntax like this existed :
unityContainer.Resolve<TypeA>(myDomainObject)
If not, I would need to know the type in advance and would be back to the same problem.
2) I have found this article mentionning that EF provides some mechanism for DI, but it seems that it is only meant to inject the framework services (PluralizationService, etc...). Otherwise it would have been a nice way to achieve that.
3) I could also not use DI in this case... It looks like by concept DI does not fit well with polymorphism. I'm not excited by this idea though.
I'd be happy to have a solution for the property injection I'm trying to achieve, or an idea of pattern I could use. However I really don't want to create a big infrastructure and obfuscate my code just for this purpose.
Note : I don't want to you use domain events in this case.
Thank you
TL;DR
Replace the IDependency parameter of the polymorphic AbstractMethod with an implementation-specific construction dependency parameter, which is injected by the IoC container, not by the consumer.
In more detail
The original class hierarchy will need to look like more like this for inheritance polymorphicism to work, as the superclass virtual method and subclass override methods must match signatures:
public abstract class TypeA // superclass
{
public abstract void AbtractMethod(IDependency dependency);
}
public class TypeB : TypeA // subclass 1
{
public override void AbtractMethod(IDependency dependency)
{
Contract.Requires(dependency is ISpecializedDependencyForB);
// ...
}
}
public class TypeC : TypeA // subclass 2
{
public override void AbtractMethod(IDependency dependency)
{
Contract.Requires(dependency is ISpecializedDependencyForC)
// ...
}
}
However, some things don't ring true with this design:
The LSP appears to be violated, since the although AbtractMethod() advertises that it accepts the base IDependency interface, the two subclasses actually depend on a specialized subclassed dependency.
It is also unusual, and arguably inconvenient, for a caller of these methods to build up the correct dependency and pass it to the method in order for it to be invoked correctly.
So, if possible, I would adopt a more conventional approach to the arrangement of dependencies, whereby the dependency is passed to the subclass constructor, and will be available to the polymorphic method when needed. This decouples the need to supply the appropriate IDependency to the method. Leave it to the IoC container to do the appropriate dependency resolution:
Use constructor injection to create the correct dependency into Classes TypeB and TypeC
If there is a secondary requirement to Expose an IDependency on the base class TypeA to consumers, then add an additional abstract property to TypeA of type IDependency (but this seems iffy)
As per Ewan's observation, the repository would need some kind of strategy pattern in order to serve up polymorphic domain entities (B or C). In which case, couple the repository to a factory to do exactly this. The concrete factory would need to be bound to the container in order to tap into Resolve().
So putting this all together, you might wind up with something like this:
using System;
using System.Diagnostics;
using Microsoft.Practices.Unity;
namespace SO29233419
{
public interface IDependency { }
public interface ISpecializedDependencyForB : IDependency { }
public interface ISpecializedDependencyForC : IDependency { }
public class ConcreteDependencyForB : ISpecializedDependencyForB {};
public class ConcreteDependencyForC : ISpecializedDependencyForC { };
public abstract class TypeA
{
// Your polymorphic method
public abstract void AbtractMethod();
// Only exposing this for the purpose of demonstration
public abstract IDependency Dependency { get; }
}
public class TypeB : TypeA
{
private readonly ISpecializedDependencyForB _dependency;
public TypeB(ISpecializedDependencyForB dependency)
{
_dependency = dependency;
}
public override void AbtractMethod()
{
// Do stuff with ISpecializedDependencyForB without leaking the dependency to the caller
}
// You hopefully won't need this prop
public override IDependency Dependency
{
get { return _dependency; }
}
}
public class TypeC : TypeA
{
private readonly ISpecializedDependencyForC _dependency;
public TypeC(ISpecializedDependencyForC dependency)
{
_dependency = dependency;
}
public override void AbtractMethod()
{
// Do stuff with ISpecializedDependencyForC without leaking the dependency to the caller
}
public override IDependency Dependency
{
get { return _dependency; }
}
}
public interface ITypeAFactory
{
TypeA CreateInstance(Type typeOfA);
}
public class ConcreteTypeAFactory : ITypeAFactory
{
private readonly IUnityContainer _container;
public ConcreteTypeAFactory(IUnityContainer container)
{
_container = container;
}
public TypeA CreateInstance(Type typeOfA)
{
return _container.Resolve(typeOfA) as TypeA;
}
}
public class TypeARepository
{
private readonly ITypeAFactory _factory;
public TypeARepository(ITypeAFactory factory)
{
_factory = factory;
}
public TypeA GetById(int id)
{
// As per Ewan, some kind of Strategy Pattern.
// e.g. fetching a record from a database and use a discriminating column etc.
return (id%2 == 0)
? _factory.CreateInstance(typeof (TypeB))
: _factory.CreateInstance(typeof (TypeC));
// Set the properties of the TypeA from the database after creation?
}
}
class Program
{
static void Main(string[] args)
{
// Unity Bootstrapping
var myContainer = new UnityContainer();
myContainer.RegisterType<ISpecializedDependencyForB, ConcreteDependencyForB>();
myContainer.RegisterType<ISpecializedDependencyForC, ConcreteDependencyForC>();
myContainer.RegisterType(typeof(TypeB));
myContainer.RegisterType(typeof(TypeC));
var factory = new ConcreteTypeAFactory(myContainer);
myContainer.RegisterInstance(factory);
myContainer.RegisterType<TypeARepository>(new InjectionFactory(c => new TypeARepository(factory)));
// And finally, your client code.
// Obviously your actual client would use Dependency Injection, not Service Location
var repository = myContainer.Resolve<TypeARepository>();
var evenNumberIsB = repository.GetById(100);
Debug.Assert(evenNumberIsB is TypeB);
Debug.Assert(evenNumberIsB.Dependency is ISpecializedDependencyForB);
var oddNumberIsC = repository.GetById(101);
Debug.Assert(oddNumberIsC is TypeC);
Debug.Assert(oddNumberIsC.Dependency is ISpecializedDependencyForC);
}
}
}
Could whatever it is that knows about the dependencies live behind an interface IDependencyProvider which has a function
IDependency GetDependency(Type type).
This could even just return an object and the class that realises the interface needs to know all the sub types and their associated dependencies.
AbstractMethod is then changed to:
void AbstractMethod(IDependencyProvider provider);
In your sub classes you then override this and call
var dependency = provider.GetDependency(this.GetType());
Your middle tier then knows nothing about the sub types or the sub dependencies.
It's an interesting problem, what I was thinking is that your repository knows about and creates the TypeB and TypeC classes and so you can add the correct dependency at that point
public class TypeARepository
{
private ISpecializedDependencyForB depB;
private ISpecializedDependencyForC depC;
public TypeARepository(ISpecializedDependencyForB depB, ISpecializedDependencyForC depC)
{
this.depB = depB;
this.depC = depC;
}
public TypeA GetById(string id)
{
if (id == "B")
{
return new TypeB(depB);
}
else
{
return new TypeC(depC);
}
}
}
The TypeB and TypeC would then implement their abstract methods with their private ref to the dependency rather than having it passed in in the method.
I come across this problem in various forms myself from time to time and it always seems to me that if there is that hard link between the types just having it setup via an injection config or the like is wrong. As it allows the installer to potentially set a bad config
This approach also allows you to inject your dependencies with unity
Thank you a lot for your interest in my question, I came up with a solution yesterday evening. The objective is to keep things transparent for the client and to take full advantage of polymorphism by syntaxes such as baseObjectReference.AbstractMethodCall().
I finally realized that I was able to achieve what I'm after by taking advantage of the static modifier and using it for DI purposes. So I have that :
public abstract class TypeA
{
public abstract void AbtractMethod();
}
public class TypeB : TypeA
{
private ISpecializedDependencyForB SpecializedDependencyForB
{
get
{
return GetSpecializedDependencyForB.CreateSpecializedDependencyForB();
}
}
public override void AbtractMethod() { // do stuff with dependency }
}
public static class GetSpecializedDependencyForB
{
public static ISpecializedDependencyForB DependencyForB
{
return CreateSpecializedDependencyForB();
}
public delegate ISpecializedDependencyForB CreateSpecializedDependencyForBDelegate();
public static CreateSpecializedDependencyForBDelegate CreateSpecializedDependencyForB;
}
And then, in my unity container I add this code :
public static void RegisterTypes(IUnityContainer container)
{
// .... registrations are here as usual
GetSpecializedDependencyForB.CreateSpecializedDependencyForB = CreateMyDomainService;
}
Having this method in the same unity config class :
private ISpecializedDependencyForB CreateMyDomainService()
{
return container.Value.Resolve<ISpecializedDependencyForB>();
}
And finally, I can simply use my object like this :
TypeA myDomainObject = database.TypeARepository.GetById(id);
myDomainObject.AbtractMethod();
And that's it !
So four things here :
The first one is that I inject the delegate that will create and instance of the service.
Then it is thread safe because static member is only written one time at the beginning of the application. All other accesses will be read. Moreover two threads won't share the same instance of the dependency since the delegate creates a new one all the time.
Also one interesting thing is that I can rely on my existing unity container configuration, no extra code is needed. It is important because my dependency may need other dependency to be constructed.
And finally the unity container is anyway also static, so there is no memory leak.
It's basically a manual and easy to set up "DI framework" sitting beside Unity.
And more importantly it works like a charm ! I'm finally satisfied with my design. I will only use this approach for polymorphic situations since injecting the right dependency in the method is easy for other situations. However it might be interesting to fully encapsulate the domain model using this approach.
If I have the following code:
public class RobotNavigationService : IRobotNavigationService {
public RobotNavigationService(IRobotFactory robotFactory) {
//...
}
}
public class RobotFactory : IRobotFactory {
public IRobot Create(string nameOfRobot) {
if (name == "Maximilian") {
return new KillerRobot();
} else {
return new StandardRobot();
}
}
}
My question is what is the proper way to do Inversion of Control here? I don't want to add the KillerRobot and StandardRobot concretes to the Factory class do I? And I don't want to bring them in via a IoC.Get<> right? bc that would be Service Location not true IoC right? Is there a better way to approach the problem of switching the concrete at runtime?
For your sample, you have a perfectly fine factory implementation and I wouldn't change anything.
However, I suspect that your KillerRobot and StandardRobot classes actually have dependencies of their own. I agree that you don't want to expose your IoC container to the RobotFactory.
One option is to use the ninject factory extension:
https://github.com/ninject/ninject.extensions.factory/wiki
It gives you two ways to inject factories - by interface, and by injecting a Func which returns an IRobot (or whatever).
Sample for interface based factory creation: https://github.com/ninject/ninject.extensions.factory/wiki/Factory-interface
Sample for func based: https://github.com/ninject/ninject.extensions.factory/wiki/Func
If you wanted, you could also do it by binding a func in your IoC Initialization code. Something like:
var factoryMethod = new Func<string, IRobot>(nameOfRobot =>
{
if (nameOfRobot == "Maximilian")
{
return _ninjectKernel.Get<KillerRobot>();
}
else
{
return _ninjectKernel.Get<StandardRobot>();
}
});
_ninjectKernel.Bind<Func<string, IRobot>>().ToConstant(factoryMethod);
Your navigation service could then look like:
public class RobotNavigationService
{
public RobotNavigationService(Func<string, IRobot> robotFactory)
{
var killer = robotFactory("Maximilian");
var standard = robotFactory("");
}
}
Of course, the problem with this approach is that you're writing factory methods right inside your IoC Initialization - perhaps not the best tradeoff...
The factory extension attempts to solve this by giving you several convention-based approaches - thus allowing you to retain normal DI chaining with the addition of context-sensitive dependencies.
The way you should do:
kernel.Bind<IRobot>().To<KillingRobot>("maximilliam");
kernel.Bind<IRobot>().To<StandardRobot>("standard");
kernel.Bind<IRobotFactory>().ToFactory();
public interface IRobotFactory
{
IRobot Create(string name);
}
But this way I think you lose the null name, so when calling IRobotFactory.Create you must ensure the correct name is sent via parameter.
When using ToFactory() in interface binding, all it does is create a proxy using Castle (or dynamic proxy) that receives an IResolutionRoot and calls the Get().
I don't want to add the KillerRobot and StandardRobot concretes to the Factory class do I?
I would suggest that you probably do. What would the purpose of a factory be if not to instantiate concrete objects? I think I can see where you're coming from - if IRobot describes a contract, shouldn't the injection container be responsible for creating it? Isn't that what containers are for?
Perhaps. However, returning concrete factories responsible for newing objects seems to be a pretty standard pattern in the IoC world. I don't think it's against the principle to have a concrete factory doing some actual work.
I was looking for a way to clean up a massive switch statement that returned a C# class to do some work (code smell here).
I didn't want to explicitly map each interface to its concrete implementation in the ninject module (essentially a mimic of lengthy switch case, but in a diff file) so I setup the module to bind all the interfaces automatically:
public class FactoryModule: NinjectModule
{
public override void Load()
{
Kernel.Bind(x => x.FromThisAssembly()
.IncludingNonPublicTypes()
.SelectAllClasses()
.InNamespaceOf<FactoryModule>()
.BindAllInterfaces()
.Configure(b => b.InSingletonScope()));
}
}
Then create the factory class, implementing the StandardKernal which will Get the specified interfaces and their implementations via a singleton instance using an IKernal:
public class CarFactoryKernel : StandardKernel, ICarFactoryKernel{
public static readonly ICarFactoryKernel _instance = new CarFactoryKernel();
public static ICarFactoryKernel Instance { get => _instance; }
private CarFactoryKernel()
{
var carFactoryModeule = new List<INinjectModule> { new FactoryModule() };
Load(carFactoryModeule);
}
public ICar GetCarFromFactory(string name)
{
var cars = this.GetAll<ICar>();
foreach (var car in cars)
{
if (car.CarModel == name)
{
return car;
}
}
return null;
}
}
public interface ICarFactoryKernel : IKernel
{
ICar GetCarFromFactory(string name);
}
Then your StandardKernel implementation can get at any interface by the identifier of you choice on the interface decorating your class.
e.g.:
public interface ICar
{
string CarModel { get; }
string Drive { get; }
string Reverse { get; }
}
public class Lamborghini : ICar
{
private string _carmodel;
public string CarModel { get => _carmodel; }
public string Drive => "Drive the Lamborghini forward!";
public string Reverse => "Drive the Lamborghini backward!";
public Lamborghini()
{
_carmodel = "Lamborghini";
}
}
Usage:
[Test]
public void TestDependencyInjection()
{
var ferrari = CarFactoryKernel.Instance.GetCarFromFactory("Ferrari");
Assert.That(ferrari, Is.Not.Null);
Assert.That(ferrari, Is.Not.Null.And.InstanceOf(typeof(Ferrari)));
Assert.AreEqual("Drive the Ferrari forward!", ferrari.Drive);
Assert.AreEqual("Drive the Ferrari backward!", ferrari.Reverse);
var lambo = CarFactoryKernel.Instance.GetCarFromFactory("Lamborghini");
Assert.That(lambo, Is.Not.Null);
Assert.That(lambo, Is.Not.Null.And.InstanceOf(typeof(Lamborghini)));
Assert.AreEqual("Drive the Lamborghini forward!", lambo.Drive);
Assert.AreEqual("Drive the Lamborghini backward!", lambo.Reverse);
}
I am basing most of my current implementation off the information provided here:
Ninject Intercept any method with certain attribute?
I use a custom planning strategy class which looks for all methods with given attributes (not ninject interceptor attributes) which will then get proxied if it matches the criteria.
An example of usage would be:
Kernel.Components.Add<IPlanningStrategy, CustomPlanningStrategy<LoggingAttribute, LoggerInterceptor>>();
This would then look for any methods which have a [Logging] attribute and will then use the logging interceptor.
However I am currently getting InvalidProxyConstructorArgumentsException from dynamic proxy when it is trying to proxy the methods with related attributes on. Now I remember reading that you need virtual methods, however I do not remember seeing that you HAD to have a parameterless constructor.
All bindings are done against interfaces, and the AOP interceptors happen via attributes and the custom proxy planning class mentioned in the link above.
So is there a way to get dynamic proxy (or the linfu version) to proxy the classes which have constructors with dependencies? (All dependencies are in the Kernel so its not like they cannot be resolved).
Looking at the proxy generating code:
https://github.com/ninject/ninject.extensions.interception/blob/master/src/Ninject.Extensions.Interception.DynamicProxy/DynamicProxyProxyFactory.cs
if (targetType.IsInterface)
{
reference.Instance = this.generator.CreateInterfaceProxyWithoutTarget(targetType, additionalInterfaces, InterfaceProxyOptions, wrapper);
}
else
{
object[] parameters = context.Parameters.OfType<ConstructorArgument>()
.Select(parameter => parameter.GetValue(context, null))
.ToArray();
reference.Instance = this.generator.CreateClassProxy(targetType, additionalInterfaces, ProxyOptions, parameters, wrapper);
}
one can see that ninject's dynamic proxy extension is only passing ConstructorArguments to the Castle Dynamic Proxy Generator.
So - without changes to the ninject extension or creating your own - you need to pass all dependencies as constructor arguments. You could also try out whether property / method injection works (see https://github.com/ninject/ninject/wiki/Injection-Patterns).
If you control the code you could add interfaces to the proxied classes and then use an "interface proxy with target". This allows to decouple proxy instantiation from target (proxied class) instantiation --> target can have dependencies ctor injected without any changes to ninject (-extensions).
Clarification:
Having the following class which should be proxied:
public interface IBar { }
public class Foo
{
public Foo(IBar bar)
{
}
}
And the following binding:
Bind<Foo>().ToSelf().Intercept().With<SomeInterceptor>();
Bind<IBar>().To<Bar>();
And then retrieving a Foo from the ninject container:
IResolutionRoot.Get<Foo>();
won't work.
Putting all constructor arguments on the ninject context to make it work
However, we can change the retrieving of Foo to make it work:
var bar = IResolutionRoot.Get<IBar>();
IResolutionRoot.Get<Foo>(new ConstructorArgument("bar", bar);
Now this is suboptimal because ninject is not doing dependency resolution automatically.
Adding interface to proxied class to make it work better
We can work around the issue by using a "interface proxy with target".
First, we add an interface to the proxied class:
public interface IFoo{ }
public class Foo : IFoo
{
public Foo(IBar bar)
{
}
}
And then we change the binding to:
Bind<IFoo>().To<Foo>().Intercept().With<SomeInterceptor>();
And then retrieving a Foo from the ninject container:
IResolutionRoot.Get<Foo>();
works.
Another, possibly easier (&uglier?) solution
According to #Daniel this works:
Add two constructor to the proxied type:
one protected constructor without parameters. This one is for DynamicProxy to create the proxy.
one public/internal constructor with the arguments, to be used by ninject to instantiate the proxied type.
Ninject will automatically pick the constructor with the most arguments it can resolve.
An alternate approach would be to use a convention based binding for all classes with a method with a [Logging] attribute. However, this means that adding a [Logging] attribute to a method will influence the binding of the object, which may be undesired.
So this is how it would work (verified to work):
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class LoggingAttribute : Attribute
{
}
public interface IClassNotToBeIntercepted
{
void DoSomething();
}
public class ClassNotToBeIntercepted : IClassNotToBeIntercepted
{
public void DoSomething() { }
}
public interface IClassToBeIntercepted
{
void DoNotLogThis();
void LogThis();
void LogThisAsWell();
}
public class ClassToBeIntercepted : IClassToBeIntercepted
{
public void DoNotLogThis() { }
[Logging]
public void LogThis() { }
[Logging]
public void LogThisAsWell() { }
}
public class LoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine("interceptor before {0}", BuildLogName(invocation));
invocation.Proceed();
Console.WriteLine("interceptor after {0}", BuildLogName(invocation));
}
private static string BuildLogName(IInvocation invocation)
{
return string.Format(
"{0}.{1}",
invocation.Request.Target.GetType().Name,
invocation.Request.Method.Name);
}
}
public class DemoModule : NinjectModule
{
public override void Load()
{
this.Bind(convention => convention
.FromThisAssembly()
.SelectAllClasses()
.Where(ContainsMethodWithLoggingAttribute)
.BindDefaultInterface()
.Configure(x => x
.Intercept()
.With<LoggingInterceptor>()));
this.Bind<IClassNotToBeIntercepted>()
.To<ClassNotToBeIntercepted>();
}
private static bool ContainsMethodWithLoggingAttribute(Type type)
{
return type
.GetMethods()
.Any(method => method.HasAttribute<LoggingAttribute>());
}
}
And a test:
[Fact]
public void InterceptorTest()
{
var kernel = new StandardKernel();
kernel.Load<DemoModule>();
kernel.Get<IClassNotToBeIntercepted>()
.DoSomething();
kernel.Get<IClassToBeIntercepted>()
.LogThis();
}
Results in the following console output:
interceptor before ClassToBeIntercepted.LogThis
interceptor after ClassToBeIntercepted.LogThis