Currently I have a simple generic abstract class with one service parameter in constructor which is resolved by dependency injection.
public abstract class CosmosCommandHandler<T>
{
protected readonly ICosmosStore<T> _cosmosStore;
protected CosmosCommandHandler(ICosmosStore<T> cosmosStore)
{
_cosmosStore = cosmosStore;
}
}
and some concrete class inheriting from it
public class FooCommandHandler : CosmosCommandHandler<Foo>
{
private readonly IFooService _fooService;
public FooCommandHandler(ICosmosStore<Foo> cosmosStore, IFooService fooService)
: base(cosmosStore)
{
_fooService = fooService;
}
}
This is all fine, but I want to add a new service to abstract class and resolve it with DI as well. My idea is that I should use constructor chaining for this, but it's not working out.
Something like this.
public abstract class CosmosCommandHandler<T>
{
private readonly IAuditService _auditService;
protected readonly ICosmosStore<T> _cosmosStore;
private CosmosCommandHandler(ICosmosStore<T> cosmosStore, IAuditService auditService)
{
_cosmosStore = cosmosStore;
_auditService = auditService;
}
protected CosmosCommandHandler(ICosmosStore<T> cosmosStore)
: this(cosmosStore, IAuditService auditService)
{
}
}
Obviously I could just pass the IAuditService from FooCommandHandler just like ICosmosStore, but that doesn't seem right as FooCommandHandler has nothing to do with IAuditService. It is out of its scope.
Is this possible to achieve?
If IAuditService is out of the FooCommandHandler scope, then create child of your CosmosCommandHandler class which will have that IAuditService. And that child also could be abstract class.
Also, you could create additional overloaded constructor for your CosmosCommandHandler class - and that FooCommandHandler class does not need to use it. But that also breaks the concept of inheritance because FooCommandHandler class has nothing to do with IAuditService.
Related
Update
Well, I wasn't sure what I was asking for so it got a bit of an XY-question/discussion.
Main problem now is that I have an abstract base class which can be seen as a service, and sub services that derives from it (properties / abstract methods).
I've tried workarounds with using Interface, but no luck. I do not need the IOtherService in my Controller, so I don't want to inject it there.
Startup:
services.AddTransient<IMyBaseService, MyBaseService>();
Base service:
public MyBaseService(IOtherService other)
{
OtherService = other;
}
public MyBaseService()
{
// this runs
}
Derived service
public class DerivedService : MyBaseService
{
public DerivedService(string x)
{
}
public DoStuff()
{
OtherService.RunSomething();
}
}
I just need IOtherService to be injected in my Base service so my child "services" can use it from an inherited property.
Or is this an example of property injection?
Base class:
public abstract class Vehicle : ICleanVehicle
{
private readonly ICleanVehicle _cleanVehicle;
public Vehicle(ICleanVehicle cleanVehicle)
{
if (cleanVehicle == null) throw new ArgumentNullException("cleanVehicle");
_cleanVehicle = cleanVehicle;
}
}
Derived class:
public class Car : Vehicle
{
private readonly ICleanVehicle _cleanVehicle;
public Car(ICleanVehicle cleanVehicle) : base(cleanVehicle)
{
_cleanVehicle = cleanVehicle;
}
}
This way you have one single constructor defining the dependencies that the derived classes require. The derived classes will then call the constructor of the base class.
I Have An IDbContext Interface In Another Assembly And A Service Stack In Another Assembly , The Base Service Class has a Property Of IDbContext and other Services Do Use Its Property.
To Make Matters Simple I Omit The Base Service Class And even in this Scenario it does not work.
here is IDbContext :
public interface IDbContext
{
}
Then I Have a DBContext Class Which Implements IDbContext.
In Another Assembly We Have This Class Which has A IDContext Property :
public class StudyFieldService : IStudyFieldService{
private readonly IDbSet<StudyField> _studyFields;
public IDbContext DbContext { get; set; }
public StudyFieldService(IDbContext db)
{
_studyFields = DbContext.Set<StudyField>();
}
}
Then I have Autofac Registry Class Which Maps Classes To Interfaces and the Registry Class Is Also in Another Assembly
This Is The Body Of The Method Which maps the types :
var builder = new ContainerBuilder();
builder.RegisterType<SalaryDbContext>().As<IDbContext>().InstancePerLifetimeScope();
builder.RegisterType<StudyFieldService>().As<IStudyFieldService>().PropertiesAutowired();
Now if I Put The IDbContext In The Constructor Param Autofac Resolves it but I Want it to be injected as a property and Automatically.
I reckon you should remove the constructor injection and change the DbContext variable name to something else or use this.DbContext to make it work.
public class StudyFieldService : IStudyFieldService{
private readonly IDbSet<StudyField> _studyFields;
public IDbContext Context{ get; set; }
public StudyFieldService()
{
_studyFields = Context.Set<StudyField>();
}
}
I guess there is a conflict on variable name with ef DbContext
I have an assembly with a lot of classes (300+) with a BaseClass and I want register a generic class with a interface.
With unity you have to register by {Name} if you want to resolve an array of objects of the interface.
I want an array of objects in the MainViewModel automatically.
Is there a way to automate this with reflection?
Any suggestions?
Example (pseudo):
public class BaseClass
{
public void doFoo();
}
public ClassNumber001 : BaseClass
{
}
public ClassNumber002 : BaseClass
{
}
public interface ISuperman
{
}
public class Superman : ISuperman where T : BaseClass
{
}
public MainViewModel(IEnumerable<ISuperman> lotsofSuperman)
{
}
Working example by hand:
container.RegisterType<ISuperman, Superman <ClassNumber001>>("ClassNumber001");
container.RegisterType<ISuperman, Superman <ClassNumber002>>("ClassNumber002");
container.RegisterType<IEnumerable<ISuperman>, ISuperman[]>();
This is something that comes to my mind that might work for you...
You can register the type as follows, and should work for the open generic.
container.RegisterType(typeof(ISuperman<>), typeof(Superman<>), ... );
Registering generic parameters and types
Hope this helps!
Yes, you'll need to use reflection to easily create all of the mappings that you want. Since you are using Unity 3 you can take advantage of Registration by Convention to provide help (with the heavier lifting) in registering the classes.
I've taken your pseudo code and translated it into real code:
public abstract class BaseClass
{
public abstract void DoFoo();
}
public class ClassNumber001 : BaseClass
{
public override void DoFoo()
{
Console.WriteLine("001 Foo");
}
}
public class ClassNumber002 : BaseClass
{
public override void DoFoo()
{
Console.WriteLine("002 Foo");
}
}
public interface ISuperman
{
void Do();
}
public class Superman<T> : ISuperman where T : BaseClass
{
private T baseClass;
public Superman(T baseClass)
{
this.baseClass = baseClass;
}
public void Do()
{
this.baseClass.DoFoo();
}
}
public class MainViewModel
{
public MainViewModel(IEnumerable<ISuperman> lotsofSuperman)
{
foreach(ISuperman superman in lotsofSuperman)
{
superman.Do();
}
}
}
Then use registration by convention to register all the generics:
IUnityContainer container = new UnityContainer();
container.RegisterTypes(
AllClasses.FromAssembliesInBasePath().Where(t => typeof(BaseClass).IsAssignableFrom(t))
.Select(t => typeof(Superman<>).MakeGenericType(t)),
t => new Type[] { typeof(ISuperman) },
t => t.GetGenericArguments().First().Name,
WithLifetime.Transient);
container.RegisterType<IEnumerable<ISuperman>, ISuperman[]>();
container.Resolve<MainViewModel>();
In the above code we get all classes that inherit from BaseClass and then construct a type Superman<> and map that to ISuperman using the name of the BaseClass. The RegisterTypes call will be equivalent to calling RegisterType for every BaseClass:
container.RegisterType<ISuperman, Superman<ClassNumber001>("ClassNumber001");
container.RegisterType<ISuperman, Superman<ClassNumber002>("ClassNumber002");
Then when MainViewModel is resolved it iterates over all ISuperman instances and calls a method which prints out:
001 Foo
002 Foo
showing that we injected 2 ISuperman instances: Superman<ClassNumber001> and Superman<ClassNumber002>.
If you need specific registrations for the BaseClasses (e.g. non-default lifetime manager) then you can use registration by convention to register those too).
There are some of the ways this can be done. One is by using XML where the type is defined lets say MyClass and IMyClass and during runtime it resolves based on the assemblies available. But a better approach in my opinion would be to create a project to which you can delegate the responsibility of loading up the dependencies.
Lets say you create a class like so:
public class MyClass : IMyClass
{
private readonly IUnityContainer _container;
#ctor
// initialie the container through the constructor
public void DoWork<Interface, Class>() where Class: Interface
{
_container.RegisterType<Interface, Class>(
//TODO: You can setup the container lifecycle which can be transient
// or singleton or custom based on your project requirement
)
}
}
Now whoever needs to register itself can call this interface IMyClass to get itself registered in the container and dependency can be injected to whichever class needs to perform that task.
After reading the new documentation on NInject v3 and how to use the Factory Extension, apparently I still don't get it fully since my code throws exceptions all over the place...
I get this Exception, i could paste the whole thing if people would like that but i'll try and keep it short for now.
Error activating IDeployEntityContainer No matching bindings are available,
and the type is not self-bindable.
Here is my code...
The Ninject Bind Module class
class MyNinjectModule : NinjectModule {
public override void Load() {
...
Bind<IDeployEntityFactory>().ToFactory();
Bind<IDeployEntityContainer>().To<DeployEntityContainer>();
...
}
}
The class which uses the factory
class DeployController : IDeployController {
private readonly IDeployEntityFactory _entityFactory;
public DeployController(..., IDeployEntityFactory entityFactory) {
...
}
public void Execute() {
...
//I get the Exception on this line...
_entityFactory.GetDeployEntity<IDeployEntityContainer>();
...
}
}
Factory Interface
public interface IDeployEntityFactory
{
T GetDeployEntity<T>();
}
The Factory Implementation
public class DeployEntityFactory : IDeployEntityFactory
{
private readonly IResolutionRoot _resolutionRoot;
public DeployEntityFactory(IResolutionRoot resolutionRoot)
{
_resolutionRoot = resolutionRoot;
}
public T GetDeployEntity<T>()
{
return _resolutionRoot.Get<T>();
}
}
Behind the scenes Ninject will create a proxy that implements the
specified factory interface and intercept all methods so that the
proxy behaves like...
I understand that I don't have to actually create the implementation my self if i don't need to do something special/custom in the creation of objects inside the factory.
Source: http://www.planetgeek.ch/2011/12/31/ninject-extensions-factory-introduction/
EDIT1:
Just to make sure i leave you with every bit of information you need to see the problem, i'm adding the DeployEntityContainer class/Interface
public abstract class DeployEntityBase : IDeployEntity
{
...
protected readonly IDeployEntityFactory _entityFactory;
protected DeployEntityBase(..., IDeployEntityFactory entityFactory)
{
...
_entityFactory = entityFactory;
...
}
...
}
public class DeployEntityContainer : DeployEntityBase, IDeployEntityContainer
{
...
public DeployEntityContainer(..., IDeployEntityFactory entityFactory)
: base(..., entityFactory)
{
}
}
I ended up just changing the bindings to normal bindings,
Bind<IMyFactory>().To<MyFactory>().InSingletonScope();
and it worked! My first thought was lol, but it makes sense as well.
With the ToFactory() binding it never ever used my implementation of the factory, it just generated one from the defined interface.
Now it uses my implementation. The factory is changed a bit: From newing up the kernel in the factory or injecting it in the constructor, now I inject IResolutionRoot which Get<T>(); my objects.
Here is the new code just for clarification.
class MyNinjectModule : NinjectModule {
public override void Load() {
...
Bind<IDeployEntityFactory>().To<DeployEntityfactory>().InSingletonScope();
Bind<IDeployEntityContainer>().To<DeployEntityContainer>();
...
}
}
public class DeployEntityFactory : IDeployEntityFactory
{
private readonly IResolutionRoot _resolutionRoot;
...
public DeployEntityFactory(..., IResolutionRoot resolutionRoot)
{
...
_resolutionRoot = resolutionRoot;
}
public T GetDeployEntity<T>()
{
return _resolutionRoot.Get<T>();
}
}
If this is not the right way to do it, I hope somebody can shed light on it and notify me with the right way... I imagine #remogloor would know such a thing. :)
Currently when I need to inject dependencies into base class, I use the following code:
public class BaseClass
{
readonly IService _service;
public BaseClass(IService service)
{
_service = service;
}
}
public class A : BaseClass
{
public A(IService service) : base(service)
{
}
}
public class B : BaseClass
{
public B(IService service) : base(service)
{
}
}
I have to write a lot of duplicate code in all sub classes. To avoid these duplicate code, I think I can use CommonServiceLocator to inject dependencies into the base class:
public class BaseClass
{
readonly IService _service;
public BaseClass()
{
_service = ServiceLocator.Current.GetInstance<IService>();
}
}
public class A : BaseClass
{
}
public class B : BaseClass
{
}
This seems to be much simpler, but I'm not sure if this is a good practice.
Thanks
Requesting a dependency from within a class is called the Service Locator Pattern, which is an anti-pattern. Prevent to minimize the dependency between your application and the IoC framework, even if it is the Common Service Locator.
I would still go for the first approach, but I agree that if the base class always needs that dependency and you have many sub types, this can become cumbersome. In that case, go for property injection:
public class BaseClass
{
public BaseClass()
{
}
public IService Service { get; set; }
}
This way your library is free from using a Service Locator. One of the greatest advantages of this approach for me, is that it makes writing unit tests much less painful.