I'm attempting to inject a property using ninject. Given the two bindings in the ninject module below, I would expect the ConcreteDependency to be injected into B. However, it seems that WhenInjectedInto doesn't consider the type being injected into, just the declaring type of the target (property in this case).
Is there a way to achieve the behaviour I expected?
static void Main(string[] args)
{
var kernel = new StandardKernel(new TestModule());
var b = kernel.Get<B>();
var c = kernel.Get<C>();
}
class TestModule : NinjectModule
{
public override void Load()
{
Bind<IDependency>().To<EmptyDependency>();
Bind<IDependency>().To<ConcreteDependency>().WhenInjectedInto<B>();
}
}
abstract class A
{
[Inject]
public IDependency Dependency { get; set; }
}
class B : A {}
class C : A {}
interface IDependency {}
class EmptyDependency : IDependency { }
class ConcreteDependency : IDependency { }
You should use constructor injection instead of property injection if possible. This is a better technique, which is recommended by Mark Seeman, because makes dependencies required for object construction explicit and object signature via constructor is more expressive. Code should look like this:
abstract class A
{
public IDependency Dependency { get; private set; }
public A (IDependency dependency)
{
Dependency = dependency;
}
}
class B : A
{
public B (IDependency dependency)
: base(dependency)
{
}
}
class C : A
{
public C (IDependency dependency)
: base(dependency)
{
}
}
interface IDependency { }
class EmptyDependency : IDependency { }
class ConcreteDependency : IDependency { }
Configuration will be the same as in you example. The following test passes
[Test]
public void TestSpecificBindingToObjectB()
{
var kernel = new StandardKernel(new TestModule());
var b = kernel.Get<B>();
var c = kernel.Get<C>();
Assert.AreNotEqual(b.Dependency.GetType(), c.Dependency.GetType());
Assert.AreEqual(typeof(ConcreteDependency), b.Dependency.GetType());
}
If you have an optional dependency with default implementation and you are ok with decorating your classes with Inject attribute, you can can pull parent information from request, like this:
class TestModule : NinjectModule
{
public override void Load()
{
Bind<IDependency>().To<EmptyDependency>();
Bind<IDependency>().To<ConcreteDependency>().When(req =>req.ParentContext.Request.Service == typeof(B));
}
}
Then the same test given above passes for your class hierarchy with property injection.
In order to check against a concrete type, you can use ParentContext.Plan.Type on the IRequest interface. This should give you the behaviour you expected from WhenInjectedInto. For example:
When(req => req.ParentContext.Plan.Type == typeof(B))
Related
I am looking on ways to improve the following code:
public interface IExample{ void Do(); }
public interface IExampleA: IExample {}
public class ExampleA: IExampleA { public void Do(); }
public interface IExampleB: IExample {}
public class ExampleB: IExampleB { public void Do(); }
public interface IExampleFactory{
IExample Make(TypesOfExamples thisIsAnEnum);
}
public class ExampleFactory: IExampleFactory {
IExampleA _exampleA;
IExampleB _exampleB;
public ExampleFactory(IExampleA exampleA, IExampleB exampleB)
{
_exampleA = exampleA;
_exampleB = exampleB;
}
public IExample Make(TypesOfExamples thisIsAnEnum)
{
switch(thisIsAnEnum)
{
case A: return _exampleA;
case B: return _exampleB;
}
}
}
Basically what I don't like is having to use the IExampleA and IExampleB, they are there only for being injected:
container.Bind<IExampleA>().To.<ExampleA>();
container.Bind<IExampleB>().To.<ExampleB>();
container.Bind<IExampleFactory>().To.<ExampleFactory>();
And it would be used like this
public class ExampleUsage()
{
ExampleFactory _exampleFactory;
public ExampleUsage(ExampleFactory exampleFactory)
{
_exampleFactory = exampleFactory;
}
public void useFactory(Test obj)
{
var implementation = _exampleFactory.Make(obj.ThisIsAnEnum);
implementation.Do();
}
}
Any pointers would be appreciated, thanks!
**Edit I had forgotten to mention that both ExampleA and ExampleB has some dependencies that need to be taken care of by the DI
public class ExampleA: IExampleA
{
IDependencyA _dependencyA;
IDependencyB _dependencyB;
public ExampleA(IDependencyA dependencyA, IDependencyB dependencyB)
{
_dependencyA = dependencyA;
_dependencyB = dependencyB;
}
public void Do();
}
public class ExampleB: IExampleB
{
IDependencyA _dependencyA;
IDependencyB _dependencyB;
IDependencyC _dependencyC;
public ExampleA(IDependencyA dependencyA, IDependencyB dependencyB, IDependencyC dependencyC)
{
_dependencyA = dependencyA;
_dependencyB = dependencyB;
_dependencyC = dependencyC;
}
public void Do();
}
container.Bind<IDependencyA>().To.<DependencyA>();
container.Bind<IDependencyB>().To.<DependencyB>();
container.Bind<IDependencyC>().To.<DependencyC>();
I think you are doing wrong with the Factory.
There is no point to inject ExampleA and ExampleB to the Factory.
Since the factory pattern is responsible for creation, therefore you can do instantiation from inside factory class.
This could be easy to replace the factory with the other implementations of the IExampleFactory.
*Edited added more details.
Actually the DI container can be considered as a factory (both are responsible for objects creation).
But if you want to go the factory way, you can implement you own instantiation logic.
Of course, you need to handle the dependencies by the factory.
The factory interface is better to define the objects to be created separately.
public interface IExampleFactory
{
IExampleA CreateExampleA();
IExampleB CreateExampleB();
}
Then the concrete factory should handle the instantiation process of each object.
you can do anything to get all dependencies to instantiate the object (each object can have different dependencies).
public class ExampleFactory: IExampleFactory
{
IExampleA CreateExampleA()
{
//instantiating concrete object A with its dependencies
return concreteA;
}
IExampleB CreateExampleB();
{
//instantiating concrete object B with its dependencies
return concreteB;
}
}
We currently have code that looks something like below, with a factory being injected in to a lot of classes, which then call the factory to get an instance of what they want.
public class Service
{
public Service(IFactory factory)
{
_car = factory.GetCar<Entity>();
}
}
public class Car : ICar
{
}
public interface IFactory
{
ICar<TEntity> GetCar<TEntity>();
IBoat<TEntity> GetBoat<TEntity>();
}
public class Factory : IFactory
{
ConnectionDetails _connectionDetails;
public Factory(ConnectionDetails connectionDetails)
{
_connectionDetails = connectionDetails;
}
TEntity GetCar<TEntity>()
{
var car = new Car<TEntity>(_connectionDetails);
car.Initialize();
return car;
}
}
I was hoping to be able to create a solution that would allow for request a dependency directly on the Car<TEntity> without needing to go through the factory first.
Below is an example of installing for a single TEntity, but how would I set this up to be generic?
I've tried using open generics, but I can't see how I can get the correct return type out of .UsingFactoryMethod().
I know I can get the RequestedType out of the CreationContext, but I don't see how I can use that to solve this problem.
public class Installer : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<ICar<TEntity>>().UsingFactoryMethod(
kernel =>
{
var factory = kernel.Resolve<IFactory>();
return factory.GetCar<TEntity>();
}));
}
}
Personally I find that factories mixed with dependency injection can be a bit of anti-pattern, since it hides implementation/creation details somewhere other than the object graph root. In addition, when mixing the two it becomes unclear who ultimately has the responsibility for creating and maintaining objects and their lifecycles.
I'd recommend you move to allowing the container to fully handle creation details based on common base interfaces/classes.
void Main()
{
var container = new WindsorContainer();
container.Install(new Installer());
var car = container.Resolve<Car>();
car.Dump();
}
public class Service
{
private ICar<CarEntity> _car;
public Service(ICar<CarEntity> car)
{
_car = car;
}
}
public class TEntity { }
public class CarEntity : TEntity { }
public class BoatEntity : TEntity { }
public interface ICreatable { }
public interface ICar<TEntity> : ICreatable { }
public class Car : ICar<TEntity>
{
private ConnectionDetails _connectionDetails;
public Car(ConnectionDetails connectionDetails)
{
_connectionDetails = connectionDetails;
Initialize();
}
public void Initialize() {}
}
public class ConnectionDetails { }
public class Installer : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<ConnectionDetails>()
.ImplementedBy<ConnectionDetails>());
container.Register(
Classes.FromAssemblyInThisApplication()
.BasedOn(typeof(ICreatable))
.WithServiceAllInterfaces()
.WithServiceSelf()
.LifestyleTransient());
}
}
You can use Castle's Typed Factory Facility to achieve this.
First you need to create an interface that Castle will implement:
public interface IFactory
{
ICar<TEntity> CreateCar<TEntity>(ConnectionDetails connectionDetails);
IBoat<TEntity> CreateBoat<TEntity>(ConnectionDetails connectionDetails);
void Release(object component); // left type as object so it can release either a boat or a car
}
With this implementation as long as your object is registered in the container with the closed generic type as its service name castle will automatically be able to find the correct object.
Then you just need to add the facility and register your factory interface:
kernel.AddFacility<TypedFactoryFacility>();
kernel.Register(Component.For<IFactory>().AsFactory());
The article I linked at the top also covers the naming semantics of the methods in the interface as some words are given special meaning.
I'm relatively new to dependency injection. I think I get the idea, but I'm now presented with this problem. Assume that I have some interfaces and some classes:
interface IA<T>
interface IB<IA<T>>
class A<T> : IA<T>
class B<IA<T>> : IB<IA<T>>
I want to register the following in my dependency injection container:
container.Register<IB<IA<T>>, B<A<T>>(...);
When I try to resolve IB<IA<T>>, it fails with an exception explaining that IB<IA<T>> cannot be converted to B<A<T>>.
Why did it fail, and how can I fix it?
Like Alexei posted already you wouldn't use generics that way. You would probably want something like this instead:
public interface IA<T>
{
T Item { get; }
}
public interface IB<T>
{
IA<T> IA { get; }
}
Sample implementations:
public class A<T> : IA<T>
{
public T Item
{
get;
set;
}
}
public class B<T> : IB<T>
{
public B(IA<T> ia)
{
this.IA = ia;
}
public IA<T> IA
{
get;
private set;
}
}
Since the subject is dependency injection notice the B implementation does not have parameterless constructor. Instead it notifies its dependency in the constructor.
Setting up the container, first register IA implementation:
container.Register<IA<int>, A<int>>(); // specific implementation or
container.Register(typeof(IA<>), typeof(A<>)); // generic registration
Registering IB would be the same and the container should take care of injecting the dependency to class B's constructor:
container.Register<IB<int>, B<int>>();
container.Register(typeof(IB<>), typeof(B<>));
Resolving at runtime you would need to specify the type:
var intIB = container.Resolve<IB<int>>();
var stringIB = container.Resolve<IB<string>>();
I am using the Autofac IOC with construcor validation. I can't figure out how to register the classes in the IOC so that LogotypeService gets LogoImageValidator and AdService get AdValidator injected in it's constructors.
I don't want to specify which instance of SomeClass that should be injected.
I have:
One validation interface (IImageValidator)
One base class for the common validation logic (ImageValidatorBase)
Two subclasses which holds specific valiation logic (LogoImageValidator and AdImageValidator)
One service interface (IService)
Two services which each should use different subclasses for validation. (LogotypeService should use LogoImageValidator) and (AdService should use AdValidator)
Interface
public interface IImageValidator
{
bool ValidFileSize();
}
Base class:
public abstract class ImageValidatorBase : IImageValidator
{
//constructor omitted
Public abstract ValidFileSize()
{
//shared code
}
}
Subclass LogoImageValidator
public class LogoImageValidator : ImageValidator
{
//constructor omitted
public override bool ValidFileSize()
{
//class specific code
}
}
Subclass AdImageValidator
public class AdImageValidator : ImageValidator
{
//constructor omitted
public override bool ValidFileSize()
{
//class specific code
}
}
IService
public interface IService{
bool ValidFileSize();
}
LogotypeService
public class LogotypeService : IService
{
private readonly ISomeClass _someClass;
private readonly IImageValidator _imageValidator;
public LogotypeService(ISomeClass someClass, IImageValidator imageValidator)
{
_someClass = someClass;
_imageValidator = imageValidator;
}
public bool ValidFileSize()
{
_imageValidator.ValidFileSize();//use LogoImageValidator subclass here
}
}
AdService
public class AdService : IService
{
private readonly ISomeClass _someClass;
private readonly IImageValidator _imageValidator;
public AdService(ISomeClass someClass, IImageValidator imageValidator)
{
_someClass = someClass;
_imageValidator = imageValidator;
}
public bool ValidFileSize()
{
_imageValidator.ValidFileSize();//use AdValidator subclass here
}
}
Any ideas?
This appears to overlap with this question: Inject Specific Type With Autofac
The answer there suggests that different interfaces be used based on context.
I have the classes below:
SuppliersRepository.cs (with the interface defining the method):
public class SuppliersRepository : BaseRepository,ISuppliersRepository
{
public IEnumerable<Supplier> GetSuppliersByCoordinates(double latitude, double longitude)
{
using (IDbConnection connection = OpenConnection())
{
const string query = "SELECT ID=SupplierID,Name=Suppliername FROM suppliers WHERE dbo.Distance(#latitude,#longitude,latitude,longitude) < 15 AND latitude IS NOT NULL AND longitude IS NOT NULL";
return connection.Query<Supplier>(query, new { latitude = latitude,longitude=longitude });
}
}
}
BaseRepository.cs (with the interface defining the method)
public abstract class BaseRepository: IBaseRepository
{
public IDbConnection OpenConnection()
{
IDbConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["myconnection"].ConnectionString);
connection.Open();
return connection;
}
}
A Bootstraper.cs called from global.asax.cs with:
public static class Bootstrapper
{
public static void Initialise()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
container.RegisterType<IBaseRepository, BaseRepository>();
container.RegisterType<ISuppliersRepository, SuppliersRepository>();
container.RegisterInstance<IHttpControllerActivator>(new HttpControllerActivator(container));
container.RegisterControllers();
return container;
}
}
And two controllers, first one resolves the repository fine:
public class VenueController : MasterController
{
[Dependency]
public SuppliersRepository _SuppliersRepository { get; set; }
}
But this one fails:
public class AjaxController : Controller
{
[Dependency]
public BaseRepository _BaseRepository { get; set; }
}
It throws a System.InvalidOperationException: The type BaseRepository cannot be constructed. You must configure the container to supply this value.
Any idea what am I doing wrong?
First of all, when using dependency injection, it's better to have dependencies on interfaces, rather than having dependencies on concrete classes. I would change your controllers to
public class VenueController : MasterController
{
[Dependency]
public ISuppliersRepository _SuppliersRepository { get; set; }
}
public class AjaxController : Controller
{
[Dependency]
public IBaseRepository _BaseRepository { get; set; }
}
Second, BaseRepository is abstract class. Instances of abstract class can not be constructed, and I think that's the reason why it fails when unity comes to actually creating BaseRepository. You should inject concrete classes.
container.RegisterType<IBaseRepository, SomeConcreteImplementationOfBaseRepository>();
You should define your classes to take a property of IRepository, e.g:
public class AjaxController : Controller
{
[Dependency]
public IRepository _BaseRepository { get; set; }
}
Your properties should always be defined in terms of the interface, not the concrete implementation, otherwise you have tied yourself to the implementation, thus making the use of dependency injection rather pointless!