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.
Related
I'm currently facing an issue for which I have found some partial solutions, but not the one that actually makes me believe I cannot do better.
So, to put in simple, I'm using the Dependency Injection, and I'm facing a circular reference error. Here's something similar to the code I am using.
First, I have a IMyBuilder interface:
public interface IMyBuilder { }
Then, I have an abstract class that implements the interface, and a bunch of class extending the abstract one:
public abstract class MyBuilderBase<DTO> : IMyBuilder
{
public abstract Dto GetDto();
}
public class UserBuilderDto : MyBuilderDto<UserDTO> { ... }
public class ProfessorBuilderDto : MyBuilderDto<ProfessorDTO> { ... }
public class AnimalBuilderDto : MyBuilderDto<AnimalDTO> { ... }
Then, I have a ProviderService, which helps me get the right IMyBuilder based on the DTO type. This ProviderServicedepends on ALL the IMyBuilder, like so:
public class ProviderService
{
private readonly IEnumerable<IMyBuilder> _builders;
public ProviderService(IEnumerable<IMyBuilder> builders)
{
_builders = builder;
}
public IMyBuilder GetBuilder<DTO>()
{
return _builders.OfType<MyBuilderBase<DTO>>().FirstOrDefault();
}
}
Finally, last piece of my code is the registration of the services, like so:
services.AddScoped<IMyBuilder, UserBuilderDto>();
services.AddScoped<IMyBuilder, ProfessorBuilderDto>();
services.AddScoped<IMyBuilder, AnimalBuilderDto>();
services.AddScoped<ProviderService>();
Notice that I register my builder as IMyBuilder: this way I can use the parameter IEnumerable<IMyBuilder> in the constructor of ProviderService.
Ok, now that we have all the inputs, here's the problem: inside the abstract method MyBuilderBase.GetDto I might need some other builder! Therefore, MyBuilderBase needs ProviderService, something like this:
public class AnimalBuilderDto : MyBuilderDto<AnimalDTO>
{
private readonly ProviderService _providerService;
public AnimalBuilderDto(ProviderService providerService)
=> (_providerService) = (providerService)
public AnimalDto GetDto()
{
// using _providerService
}
}
At this point you can clearly see where is my problem:
ProviderService requires AnimalBuilderDto
AnimalBuilderDto requires ProviderService
ProviderService requires AnimalBuilderDto
...
Circular dependency, thus my application crashes.
So, I've investigated this for a while, and I've come up with these solutions.
LAZY INITIALIZATION IN PROVIDER SERVICE
This would be something like here: https://thomaslevesque.com/2020/03/18/lazily-resolving-services-to-fix-circular-dependencies-in-net-core/
Basically, in the constructor of ProviderService I would not directly need to initialize the single IBuilderDto, avoiding the circular dependency..
What I don't like is that it seems a workaround, and not a solution. Also, if by any chance I put a breakpoint into providerService constructor, and inspect the lazy property, the application crashes.. Yeah, workaround.
METHOD INJECTION
I would need to change the signature of the abstract method as follow:
public abstract Dto GetDto(ProviderService providerService);
This way, I would not need the AnimalBuilderDto to depends on ProviderService, REMOVING the circular dependency.
This solution seems a real solution (it removes the circular dependency), but it adds a cost, which is the need of bringing this instance of ProviderService along all the application in order to use it when calling GetDto.
Here's end my investigation. Though, both solution does not seems to fix my problem! Ok, the second one does actually fix the problem, but create another one, which is the need of bringing the instance across all method calls.
Question is: is there any better solution to make a provider class like my ProviderService being reusable inside the same classes that it exploses?
Here's a quick and dirty way to break the circular reference, using an open generic service locator factory.
public interface IMyBuilder<TDTO>
{
TDTO GetDto();
}
public class BuilderFactory<TDTO>
{
private readonly IServiceProvider services;
public BuilderFactory(IServiceProvider services)
{
this.services = services;
}
public IMyBuilder<TDTO> GetBuilder() => services.GetRequiredService<IMyBuilder<TDTO>>();
}
public abstract class MyBuilderBase<DTO> : IMyBuilder<DTO>
{
public abstract DTO GetDto();
}
public class UserDTO { }
public class UserBuilderDto : MyBuilderBase<UserDTO>
{
private BuilderFactory<AnimalDTO> animalFactory;
public UserBuilderDto(BuilderFactory<AnimalDTO> animalFactory)
{
this.animalFactory = animalFactory;
}
public override UserDTO GetDto()
{
var animalBuilder = animalFactory.GetBuilder();
throw new NotImplementedException();
}
}
public class AnimalDTO { }
public class AnimalBuilderDto : MyBuilderBase<AnimalDTO>
{
private BuilderFactory<UserDTO> userFactory;
public AnimalBuilderDto(BuilderFactory<UserDTO> userFactory)
{
this.userFactory = userFactory;
}
public override AnimalDTO GetDto()
{
var userBuilder = userFactory.GetBuilder();
throw new NotImplementedException();
}
}
services.AddScoped(typeof(BuilderFactory<>));
services.AddScoped<IMyBuilder<AnimalDTO>, AnimalBuilderDto>();
services.AddScoped<IMyBuilder<UserDTO>, UserBuilderDto>();
Create an event in consumer class and fire it , once fired make the server class return its current instance
If the Builders use functions from ProviderService that use the Builders too, creating a factory is a way to break the cycle (at least in terms of timing, because the instances of the Builders are created at a later point in time and not upon registration.
However, if the Builders use only functions from ProviderService that do not rely on the Builders themselves, one other option is to move the functionality that is used in GetDto into another class that can be injected into both the Builders and the ProviderService. This way, the circular dependency is removed and both classes still have access to the functionality.
Basically, from
ProviderService -> Builders -> ProviderService
to
ProviderService -> Builders -> SharedFunctions
-> SharedFunctions
Whether or not the Builders and the ProviderService use the same instance of SharedFunctions then depends on the scope that you register it in the IoC container.
Hello i have to create a complex object , and i wanted to use the factory pattern for it.However i do not know what to do with the additional dependencies that the object needs in order to be created.
Dependencies
public class SomeService
{
}
public class SomeOtherService
{
}
Hierarchy
public abstract class NeededObjectBase
{
public readonly int Type {get;set;} //id selected by the factory
public abstract void DoSomething();
}
public class A:NeededObjectBase
{
private SomeService service;
A(SomeService service){ this.service=service;}
public override void DoSomething(){}
}
public class B:NeededObjectBase
{
public B(SomeService service,SomeOtherService otherService){
this.service=service;
this.otherService=otherService
}
public SomeOtherService service;
public SomeOtherService otherService;
public override void DoSomething(){}
}
Factory
public class Factory
{
public static NeededObjectBase CreateInstance(int type)
{
switch(type)
{
case 0:return new A(); //this would need SomeService => new A(someService)
case 1:return new B(); // this would need SomeService & SomeOtherService => new B(someService,someOtherService);
default: return new A();
}
}
}
Usage
public class Aggregate
{
private SomeService s1;
private SomeOtherService s2;
public void UseNeededObject(int type)
{
NeededObjectBase neededObject=Factory.CreateInstance(type);
neededObject.DoSomething();
}
}
If you look in the code things happen like this:
I have an Aggregate class where i keep my dependencies.Inside its method i use the Factory based on the type parameter in order to create the right object.However i do not know what to do with the dependencies.Should the factory get all the required dependencies in order to create the objects ?
So basically i do not know who should keep the dependencies for object creation.The factory makes the selection but how does it provide the right dependencies in order to instantiate the selection ?
P.S I would need somehow to first make the selection based on the parameter and retrieve something from the factory and then that something to get its dependencies in order to create the final object.
One good way of doing this is to use a DI library and to then inject whatever container it provides into the factory; the factory is then only deciding based on the passed parameters what type it should return, and then delegating to the container to construct that object for return.
This has some benefits
It lets you separate the lifecycle of these dependent objects (and indeed, the constructed objects) from the factory
It decouples the factory from having to know how to construct all the possible object graphs it provides and lets it focus on making the decision on what to build, not how to build it
e.g.
public class SimpleFoo: Foo
{
public SimpleFoo(IServiceA a){...}
}
public class ComplexFoo: Foo
{
public ComplexFoo(IServiceA a, IServiceB b){...}
}
public class DegenerateFoo: Foo
{
public DegenerateFoo(){..does nothing...}
}
public class FooFactory
{
readonly IContainer _container;
public void FooFactory(IContainer container){_container=container;}
public Foo GetAFoo(int type)
{
switch (type)
{
case 0:
return _container.Get<SimpleFoo>();
case 1:
return _container.Get<ComplexFoo>();
default:
//unknown case, return some kind of Foo that does nothing
return _container.get<DegenerateFoo>();
}
}
}
Your container, meanwhile, would have been separately configured somewhere else in the application's "Composition Root" to know how to resolve the object graphs (the following is pseudocode only)
container.RegisterTransient<IServiceA, ServiceAImplementation>();
container.RegisterSingleton<IServiceB, ServiceBImplementation>();
In this case we're configuring that any IServiceA injection is a new object instance each time it is requested; whereas IServiceB injections will be a single shared instance that the container takes care of creating once and doling out on request. Of course this is just an example of how you might configure these, ultimately you know best how you need to configure the lifetimes of these dependencies.
Hope you get the idea.
I am trying to get IoC working with Unity in C# with the idea of a passing a wrapper/composite class into the children.
The top level class that composes multiple classes provides some common functionality that the composed classes require access to.
To illustrate:
// The top composite class
public class Context : IContext {
public ISomething SomethingProcessor { get; }
public IAnother AnotherProcessor { get; }
public Context(ISomething something, IAnother another) {
this.SomethingProcessor = something;
this.AnotherProcessor = processor;
}
// A function that individual classes need access to, which itself calls one of the children.
public string GetCommonData() {
return this.AnotherProcessor.GetMyData();
}
}
public class Something : ISomething {
private _wrapper;
public Something(IContext context) {
this._wrapper = context;
}
// This class has no knowledge of IAnother, and requests data from the master/top class, which knows where to look for whatever.
public void Do() {
Console.WriteLine(_wrapper.GetCommonData());
}
}
public class Another : IAnother {
public string GetMyData() {
return "Foo";
}
}
If you didn't use IoC, it's easy, as the constructor for the Context class becomes:
public Context() {
this.SomethingProcessor = new Processor(this);
this.AnotherProcessor = new Another();
}
But when you're using IoC, the idea of "this" doesn't exist yet because it is yet to be constructed by the injector. Instead what you have a is a circular dependency.
container.RegisterType<ISomething, Something>();
container.RegisterType<IAnother, Another>();
container.RegisterType<IContext, Context>();
var cxt = container.Resolve<IContext>(); // StackOverflowException
The above example has been greatly simplified to illustrate the concept. I'm struggling to find the "best practice" way of dealing with this kind of structure to enable IOC.
Factory pattern is a way construct an object based on other dependencies or logical choices.
Factory Method: "Define an interface for creating an object, but let
the classes which implement the interface decide which class to
instantiate. The Factory method lets a class defer instantiation to
subclasses" (c) GoF.
Lots of construction.. hence the name Factory Pattern
A crude code sample that could be used with DI
public class ContextFactory : IContextFactory {
_anotherProcessor = anotherProcessor;
public ContextFactory(IAnotherProcessor anotherProcessor) {
//you can leverage DI here to get dependancies
}
public IContext Create(){
Context factoryCreatedContext = new Context();
factoryCreatedContext.SomethingProcessor = new SomethingProcessor(factoryCreatedContext )
factoryCreatedContext.AnotherProcessor = _anotherProcessor;
//You can even decide here to use other implementation based on some dependencies. Useful for things like feature flags.. etc.
return context;
}
}
You can get away with this, maybe? - but there is still the cyclic reference issue here and I would never commit this kind of code.
The problem here you need to concentrate on Inversion Of Control of that GetCommonData
Your SomethingProcessor should not rely on methods in another class. This is where In Inheritance could be used but Inheritance can become very complicated very quickly.
The best way forward is to Identify the ONE thing that is needed by both or many other places and break that out into a new Dependency. That is how you Invert Control.
TIP:
Don't overdo Interfaces- Use Interfaces where you think you will be working with Polymorphism, such as a collection of different objects that must promise you they have implemented a specific method/property. Otherwise you are over using Interfaces and increasing complexity. DI doesn't have to use Interfaces it can be a concrete implementation. Interfaces on Repositories are a good use since you can switch Databases out easily but Interfaces a factory like this is not really needed.
I don't know the name of this pattern, or even if it is a bad or good practice, but you can solve your problem of "double-binding" by creating a method to bind the "IContext", instead of doing it in the constructor.
For instance,
1) ISomething has a void BindContext(IContext context) method
2) You implement it as such :
class Something : ISomething
{
IContext _wrapper;
// ... nothing in constructor
public void BindContext(IContext context)
{
_wrapper = context;
}
}
3) Remove the IContext dependency injection in Something constructor.
And you call it from the context constructor :
public Context(ISomething something, IAnother another) {
this.SomethingProcessor = something;
this.SomethingProcessor.BindContext(this);
// same for IAnother
}
And you do the same for IAnother. You could even extract some common interface "IBindContext" to make things a beat more "DRY" (Don't Repeat yourself) and make IAnother and ISomething inherit from it.
Not tested, and again : not sure it's the best way to do such dependency design. I'll be glad if there is another answer which gives a state-of-the-art insight about this.
I am getting confused with the scenario of 2 classes implementing the same interface and Dependency Injection.
public interface ISomething
{
void DoSomething();
}
public class SomethingA : ISomething
{
public void DoSomething()
{
}
}
public class SomethingAB : ISomething
{
public void DoSomething()
{
}
}
public class Different
{
private ISomething ThisSomething;
public Different(ISomething Something)
{
ThisSomething = Something;
}
}
I have seen online examples say that this is valid but you would only use one class at a time. So if the app is running at SiteA you tell your IOC to use SomethingA but if its at SiteB you tell it to use SomethingAB.
Is it considered bad practice therefore to have one app that has 2 classes that implement 1 interface and for it to try to use both classes? If its not how do you tell the IOC which class to use in the relevant circumstance?
UPDATE: To explain it better I will use Ninject's example:
public class Samurai
{
private IWeapon Weapon;
public Samurai(IWeapon weapon)
{
this.Weapon = weapon;
}
}
public class Sword : IWeapon
{
...
}
public class Gun : IWeapon
{
...
}
public class WarriorModule : NinjectModule
{
public override void Load()
{
this.Bind<IWeapon>().To<Sword>();
this.Bind<IWeapon>().To<Gun>(); //Just an example
}
}
So now you have 2 classes that use IWeapon. Depending on something or a context in your app you want Samurai to have a Sword sometimes or a Gun at other points. How do you make this happen? How do you handle that "if" scenario??
I don't think that this is a bad practice in the general case. There are situations where you could need different implementations of the same interface inside the same application and based on the context use one or another implementation
As far as how to configure your DI to enable this scenario, well, it will depend on your DI of course :-) Some might not support it, others might not, others might partially support it, etc..
For example with Ninject, you could have the following classes:
public interface ISomething
{
}
public class SomethingA : ISomething
{
}
public class SomethingB : ISomething
{
}
public class Foo
{
public Foo(ISomething something)
{
Console.WriteLine(something);
}
}
public class Bar
{
public Bar(ISomething something)
{
Console.WriteLine(something);
}
}
and then use named bindings when configuring the kernel:
// We create the kernel that will be used to provide instances when required
var kernel = new StandardKernel();
// Declare 2 named implementations of the same interface
kernel.Bind<ISomething>().To<SomethingA>().Named("somethingA");
kernel.Bind<ISomething>().To<SomethingB>().Named("somethingB");
// inject SomethingA into Foo's constructor
kernel.Bind<Foo>().ToSelf().WithConstructorArgument(
"something", ctx => ctx.Kernel.Get<ISomething>("somethingA")
);
// inject SomethingB into Bar's constructor
kernel.Bind<Bar>().ToSelf().WithConstructorArgument(
"something", ctx => ctx.Kernel.Get<ISomething>("somethingB")
);
Now when you request an instance of Foo it will inject SomethingA into it its constructor and when you request an instance of Bar it will inject SomethingB into it:
var foo = kernel.Get<Foo>();
var bar = kernel.Get<Bar>();
i worked with Unity and spring in this context and i think that interest lies in having a weak coupling between packages, ie classes, the ability to change service or point of entry is a consequence of the ioc.
ioc provides flexibility in the use of service, or from the time the services implement the same interface,
If Utilize Service A Service B and Service is in the service package A and package B is in B.
Package A has no reference on the package b, but the service A has a reference on the package containing the interfaces.
Therefore we conclude that we have a weak coupling between package A and package b.
Having multiple implementations mapped to the same interface isn't really bad practice, but it isn't he most common usage pattern.
You didn't specify a specific DI tool, but if you use Unity, you can do this with named instances. See here: Unity - how to use multiple mappings for the same type and inject into an object
maybe this is easy, but searching it on the internet already give me a head ache
here is the problem:
interface IValidator
{
void Validate(object obj);
}
public class ValidatorA : IValidator
{
public void Validate(object obj) { }
}
public class ValidatorB : IValidator
{
public void Validate(object obj) { }
}
interface IClassA { }
interface IClassB { }
public class MyBaseClass
{
protected IValidator validator;
public void Validate()
{
validator.Validate(this);
}
}
public class ClassA : MyBaseClass, IClassA
{
//problem: validator should ValidatorA
public ClassA(IValidator validator) { }
}
public class ClassB : MyBaseClass, IClassB
{
//problem: validator should ValidatorB
public ClassB(IValidator validator) { }
}
public class OtherClass
{
public OtherClass(IClassA a, IClassB b) { }
}
//on Main
var oc = container.Resolve<OtherClass>();
Any idea?
EDIT
I registered ValidatorA and ValidatorB with Named, now the problem how Castle Windsor can inject those validator properly to the ClassA and ClassB, is there a way to do that? or is there any better solution?
if there is someone think my class design is wrong please, i open for any advice. So far i think it correct. Yes, validator have specific configuration for specific Class. but there are reasons it is abstracted:
Validator is a complex object, sometime should connect to database, so I MUST pass interface instead of implementation to constructor for unit testing reason.
No way to use different interface for any of Validator, because the only method that i used is Validate
I think MyBaseClass.Validate() a common template method pattern isn't it?
Without going into the details of your chosen architecture just focusing on the Windsor container configuration:
If you have registered multiple named implementation to a given interface (IValidator), you can specify which one do you want to use when registering the consumer classes (ClassA, ClassB) with using ServiceOverrides:
The following container configuration providers an OtherClass with ClassA instance with a ValidatorA and ClassB instance with a ValidatorB:
var container = new WindsorContainer();
container.Register(Component.For<IClassA>().ImplementedBy<ClassA>()
.DependsOn(ServiceOverride.ForKey<IValidator>().Eq("ValidatorA")));
container.Register(Component.For<IClassB>().ImplementedBy<ClassB>()
.DependsOn(ServiceOverride.ForKey<IValidator>().Eq("ValidatorB")));
container.Register(Component.For<IValidator>().ImplementedBy<ValidatorA>()
.Named("ValidatorA"));
container.Register(Component.For<IValidator>().ImplementedBy<ValidatorB>()
.Named("ValidatorB"));
container.Register(Component.For<OtherClass>().ImplementedBy<OtherClass>());
var oc = container.Resolve<OtherClass>();
It appears that you're trying to put tight couples (ClassA with ValidatorA, ClassB with ValidatorB) as independent types into a common container. This is pointless. If you must rely on tight coupling like this, forget dependency injection in this regard and just hard-reference the types.
This would make more sense if you could implement a common validator for all classes. For instance, make the classes responsible for providing validation rules, and let Validator
just enforce the rules. Or perhaps just include the whole validation inside your classes, which is probably the most sensible scenario here.
MyBaseClass.Validate() look like inversion of control, but not like a template method.