Given a set of interfaces where for each interface there is a corresponding implementing class with the same name (e.g.: ISomeThing : SomeThing), is there a way to automatically resolve all without creating explicit mappings?
There is probably an IoC container that has this already..
This is default convention for StructureMap. It tries to connect concrete classes to interfaces using the I[Something]/[Something] naming convention.
public interface ISpaceship { }
public class Spaceship : ISpaceship { }
public interface IRocket { }
public class Rocket : IRocket { }
[Fact]
public void default_scanning_in_action()
{
var container = new Container(_ =>
{
_.Scan(x =>
{
x.Assembly("<AssemblyNameWhereClassesAreDefined>");
x.WithDefaultConventions();
});
});
var spacesfip = container.GetInstance<ISpaceship>().ShouldBeOfType<Spaceship>();
var rocket = container.GetInstance<IRocket>().ShouldBeOfType<Rocket>();
}
Related
I have a scenario where there are multiple classes that implement the same interface. the consuming class is to get all the interface implementations as a list so that it can invoke method on all the instances.
public interface IDoSomething
{
void Do();
}
public class Dance : IDoSomething
{
public void Do() { }
}
public class Eat : IDoSomething
{
public void Do() { }
}
public class Person
{
public Person(IEnumerable<IDoSomething> actions)
{
foreach (IDoSomething ds in actions)
{
ds.Do();
}
}
}
How do I register the types so that class Person can resolve all the types that implement IDoSomething. This was possible with Unity, MEF and Spring.NET IOC containers. Trying to do the same with Dry IOC.
You just need to register multiple things as usual with the same interface and whatever implementations. Then inject IEnumerable of your interface, or you may use any other collection interface implemented by .NET array.
Example:
var container = new Container();
container.Register<IDoSomething, Dance>();
container.Register<IDoSomething, Eat>();
container.Register<Person, Person>();
For more information, see the documentation.
I'm trying to figure out how to use multiple implementation of a base class with generics via dependency injection in .net core.
My base class is using generics so I can have different types of List in my response Dto.
I have successfully used many interface and base class implementations when there are no generics involved.
What I've tried so far.
Base class
public abstract class GeneratorBase<T>
{
public abstract ProcessorResponse<T> Process();
}
Response dto
public class ProcessorResponse<T>
{
public ProcessorResponse()
{
Data = new List<T>();
}
public List<T> Data { get; set; }
}
Implementation number 1
public class ConfigurationGenerator : GeneratorBase<ConfigurationModel>
{
public override ProcessorResponse<ConfigurationModel> Process()
{
return new ProcessorResponse<ConfigurationModel>();
}
}
Implementation number 2.
public class ApplicationGenerator : GeneratorBase<ApplicationModel>
{
public override ProcessorResponse<ApplicationModel> Process()
{
return new ProcessorResponse<ApplicationModel>();
}
}
Models
public class ConfigurationModel
{
public int Count { get; set; }
}
public class ApplicationModel
{
public string Title { get; set; }
}
My dependency injection to add the implementations.
public static void AddGenerators(this IServiceCollection services)
{
// add our generators
services.AddScoped<GeneratorBase<ConfigurationModel>, ConfigurationGenerator>();
services.AddScoped<GeneratorBase<ApplicationModel>, ApplicationGenerator>();
}
Main App this is where my error is happening.
public class GeneratorApp
{
// error because T is not implemented
private readonly IEnumerable<GeneratorBase> _generators;
// error because T is not implemented
public GeneratorApp(IEnumerable<GeneratorBase> generators)
{
_generators = generators ?? throw new ArgumentException(nameof(generators));
}
public void RunGenerator(string name)
{
// get the generator by name and run process
var generator = _generators.FirstOrDefault(c => c.GetType().Name == name);
var results = generator.Process();
}
}
Update IFoo Example
IFoo example that works.
public interface IFoo
{
string Name { get; }
}
public class Foo1 : IFoo
{
public string Name => "I'm Foo 1";
}
public class Foo2 : IFoo
{
public string Name => "I'm Foo 2";
}
Dependency injection to add the implementations.
public static void AddGenerators(this IServiceCollection services)
{
// add our Foo's
services.AddTransient<IFoo, Foo1>();
services.AddTransient<IFoo, Foo2>();
}
Main App
public class GeneratorApp
{
private IEnumerable<IFoo> _foos;
public GeneratorApp(IEnumerable<IFoo> foos)
{
_foos = foos;
RunGenerator("Foo1");
}
public void RunGenerator(string name)
{
foreach (var foo in _foos)
{
Console.WriteLine(foo.Name);
}
var foundFoo = _foos.FirstOrDefault(c => c.GetType().Name == name);
if (foundFoo != null)
{
Console.WriteLine(foundFoo.Name);
}
}
}
Console output
I'm Foo 1
I'm Foo 2
I'm Foo 1
The basics
You're misunderstanding the purpose (and correct usage) of dependency injection.
services.AddScoped<IFoo, Foo>();
To put it into words:
If you're creating a object whose constructor needs an IFoo, please insert a Foo instance.
That is the intention of dependency injection: to provide concrete objects even though they (the class' constructors) are asking for vague types.
It allows the classes to be vague, and thus not strongly depend on any particular implementation (= concrete classes).
Your problem
Very simply put, your constructor is asking a parameter type (IEnumerable<GeneratorBase>) that you never registered.
You only registered GeneratorBase<ConfigurationModel> and GeneratorBase<ApplicationModel>, which means that your dependency injection is only able to resolve constructor parameters of those two types. Anything else, the DI framework will throw an exception as it doesn't know how to fill it in.
The solution
It seems like you want a list of all (chosen) types to be injected. Therefore, you must register this exact type. For example:
services.AddScoped<IEnumerable<GeneratorBase>>(() => new List<GeneratorBase>()
{
new ConfigurationGenerator(),
new ApplicationGenerator()
});
This is just the shortest path to workable code. However, there are still further considerations, but your intention and use case simply isn't clear. I strongly suggest reading up on dependency injection as you are missing key knowledge on how to effectively leverage it.
Footnote: You did not post a definition for GeneratorBase (non-generic) but you did reference this type. I'm going to assume that this type exists and you forgot to add it to the question. If not, then there are also some misgivings about polymorphism with generics, which I also suggest you brush up on.
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.
having the class:
public class SomeClass{
public SomeClass(IBlabla bla, string name){
//....
}
}
I can write factory:
public class SomeClassFactory{
public SomeClassFactory(IBlabla bla){
//....
}
public SomeClass Create(string name){return new SomeClass(_bla, name)}
}
And live with it. But I wonder, is there any solution to do this without such obvious factory implementation, in the same way as .AsFactory() works, but with additional parameter?
Definitely possible, and you can even do it without an implementation through the typed factories in Castle. Here is how :
Given your base classes:
public interface IBlabla
{
}
public class Blabla : IBlabla
{
}
public class SomeClass
{
public string Name { get; set; }
public IBlabla Blabla { get; set; }
public SomeClass(IBlabla bla, string named)
{
Blabla = bla;
Name = named;
}
}
you can create a generic factory for elements with a string named in their constructor:
public interface IFactory
{
T Build<T>(string named);
}
No need for any implementation, you are going to use a tool that will create an automatic implementation of your factory backed up by Castle:
// container
var container = new Castle.Windsor.WindsorContainer();
// factory facility, needed to add behavior
container.AddFacility<TypedFactoryFacility>();
// let's register what we need
container.Register(
// your factory interface
Component.For<IFactory>().AsFactory(),
// your IBlabla
Component.For<IBlabla>().ImplementedBy<Blabla>(),
// component, you could register against an interface
Component.For<SomeClass>().ImplementedBy<SomeClass>()
);
// shazam, let's build our SomeClass
var result = container.Resolve<IFactory>().Build<SomeClass>("bla?");
Why does it work? When going through a typed factory, Castle will try and hand the object being resolved all the parameters that are passed to the factory call. So the named parameter is given to the constructor of your SomeClass. The IBlabla is resolved through standard behavior for Castle.
There you are, factory without any implementation are neat :D
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))