I have an abstract base class, and a derived class. I'm trying to use MEF to inject a reference to to my WindowManager, by using [ImportingConstructor], in the base class.
ie.
[ImportingConstructor]
public SomeViewModel(IWindowManager windowmanager) {...}
The issue is that before I added this, all I had was no param constructors, and the derived class is complaning about If I add a no param constructor to the base class, the WindowManager never gets injected.
Using my currently limited knowledge the only way I can think of is to change the manager import to a Property Import, and just have a no param default constructor. This kind of bugs me, as the general rule seems to prefer constructor injection for required dependencies, and property injection for optional ones.
I could add overriding [ImportingConstructor]s in my subclasses, but that seems like unnecessary duplication of code.
Is there a nicer way to do this, ie making sure my dependencies are getting injected in when the derived classes are created?
Ignore MEF for a moment and consider this:
public abstract class BaseClass {
protected BaseClass(IService service) { }
}
public class SubClass : BaseClass {
public SubClass(IService service) : base(service) { }
}
Because the base class defines a single constructor, the subclass must initialise the base class, by providing an argument for the base class' constructor.
Now, with MEF, what I think you are trying to do is this:
public abstract class BaseClass {
[ImportingConstructor]
protected BaseClass(IService service) { }
}
[Export]
public class SubClass : BaseClass {
public SubClass() { }
}
It sounds like you are trying to inject something into the constructor of the base class, but you can't do that, because its the resposibility of the subclass to ensure the appropriate arguments are passed to the base class of the constructor. You need to make a modification to your subclass:
[Export]
public class SubClass : BaseClass {
[ImportingConstructor]
public SubClass(IService service) : base(service) { }
}
Now the subclass will have the service injected and will pass it to the base class.
In terms of using Property Injection vs Constructor Injection: it is preferable to initialise a type into a usable state. That being any explicit dependencies should be required in the constructor. But, because MEF will satisfy all imports, by the time you've got your part back from the container, both constructor and property injections would have already occurred, so you could potentially use property imports instead. My preference has always been to go with constructor imports.
Related
I have following easy class design, where myObject is importing for BaseClass.
public abstract class BaseClass
{
public BaseClass(myObject parameter)
{
// ...
}
}
public class ChildClass : BaseClass
{
}
My problem is now, that I want to make my program extensible by inheriting from public BaseClass. So you could create a constructor
public ChildClass() :base(new myObject()){...}
which will lead to failures. Is there a possibilty to prevent inherited classes with own constructors? I actually would like to avoid constructors for ChildClass at all. Is this possible? Then I could use a factory and provide an Initialize method. Or is this something impossible, where I simply must be aware of and check in my code=
Classes are completely responsible for their own constructors. They aren't inherited, and every class must have a constructor. So no, there's nothing you can do to "control" what constructors a base class can or can't have.
I have a group of services that get injected into my controllers. Can my abstract class constructor instantiate new instances of commonly used objects?
public class ReportService : AReportService, IReportService
{
private readonly IMyService _myservice;
public ReportService(IMyService myService) : base ()
{
_myservice = myService;
}
public void MyMethodForThisService(string someProperty)
{
_parentService.DoSomething(someProperty);
}
}
public abstract class AReportService
{
protected readonly ParentService _parentService;
protected AReportService()
{
_parentService = new ParentService();
}
protected void MyFirstSharedMethodForAllServices(string someProperty)
{
_parentService.DoSomethingElse(someProperty);
}
}
Jon Skeet (as usual) is correct--you can do this. However, since you're following a Dependency Injection pattern with your child controllers, you should probably use dependency injection for your parent class as well.
You can do this by injecting the dependency into the parent's constructor, but as you've probably noticed that requires all the child classes to inject the same object and do a pass-through, which can get annoying as you add more dependencies.
Alternatively, you can do Property Injection, but this can make it easy to forget to update unit tests with new properties that need to be injected.
As a compromise, I'll often use Method injection, where the base class has an "InjectDependencies" method that initializes the dependencies. Unfortunately, this disallows you from making your dependencies read-only, and still makes it possible to construct your object without providing dependencies.
A final option would be to create a special class just for containing the parent class's dependencies, and then inject that class into the parent class's constructor. Child classes then need only pass through a single parameter into the parent constructor, and you're free to add dependencies in the future, which will not affect the child classes, but will alert unit tests that try to construct the dependency object by hand.
You should also think carefully about whether you're using inheritance in a situation where you should be using composition. Is MyFirstSharedMethodForAllServices() just a convenience method that you happen to know that several services will use? Why not just create a separate class with this method, which all of those services can inject? This would give you more flexibility, for example, to unit test MyFirstSharedMethodForAllServices() independently. It also leaves your services free to extend some other class based on a more "is a"-style relationship.
Can my abstract class constructor instantiate new instances of commonly used objects?
Absolutely. The constructor for an abstract class can do basically anything a normal constructor can. The only restriction is that you can only call the constructor as part of chaining from another constructor.
I have a base class and several subclasses derived from that base class. I also have a static function in the base class that takes some parameters, and instantiates and returns an appropriate subclass based on input parameters ( my factory method.)
Now here's my problem: I want to ONLY allow instantiation of the subclasses FROM the factory method. But if I set the constructors of the subclasses to be protected, the base class can't see them. Is there an access modifier I'm missing that would allow the base class to call the subclasses constructors, but not not allow any other classes to call them?
Internal doesn't look like it will work either...I want to limit access to the subclass constructors to just the base class, there are other classes in the same assembly that should be able to access the base factory method and but not directly instantiate any of the subclasses.
Hopefully there's something really simple I'm missing...
Example:
public class Base
{
public Base CreateChild(string childType)
{
if(childType == "A")
return new ChildA();
if(childType == "B")
return new ChildB();
return null;
}
}
public class ChildA
{
protected ChildA() // This doesn't work, since now base class can't call this!
{
}
}
public class ChildB
{
protected ChildB()
{
}
}
You can declare the child classes as private nested classes inside Base
Have you tried declaring the child classes within the base class?
public class Base {
protected class ChildA {}
protected class ChildB {}
}
If accessing any derived object through the base type is a valid scenario (let's say derived types only override base implementations and do not add new functionality) then the proposed solution of making the derived types nested private classes (as previous answers propose) is the best solution.
If that's not the case then I think you are falling into a case of unjustified complexity. What is the reason why code from your same assembly can not access ChildA and ChildB constructors? It is after all code you can control, so you can always choose to make / enforce via code review that he initalization is through the factory method.
I understand there is valid reasons to not let external assemblies freely instantiate objects except through a tightly controlled mechanism. In this case just marking the constructors as internal would do.
Otherwise, I'm not sure you can achieve what you are pretending without creating a specific assembly just for this base class and its derived classes. There is definitely no access modifier that would make a static method in a derived class only visible from it's base class.
Building on my last question, is it possible to make a derived class inherit its base's constructor? For example, if I defined two classes like this:
class Base {
public Base(){}
}
public Derived() {
}
The base class's constructor will automatically be called when the derived class is instantiated. If I add another constructor to to the base class though,
class Base {
public Base(int x){}
}
Is it possible to construct the derived class using that constructor? I mean without having to add something like
public Derived() {
public Derived(int x) : base(x) {}
}
No, it isn't. You must explicitly add them; the only default is the parameterless constructor calling base(), which you get if you don't add any constructors. It might be nice in a few cases (especially when there are lots of constructors on the base), and I imagine there are some tools (maybe R# ? I haven't checked) that might help automate it - but nothing built in.
Sort of...
class Base {
protected Base() : this(default(int)) {}
public Base(int x){}
}
public Derived() {
}
Will force Derived to call the overloaded constructor with the default value of the argument. This may, or may not, be what you want to happen though. By marking the default constructor as protected, you prevent outside callers from instantiating with the default constructor but allow derived classes to do so.
I feel like this is something I should already know, but I'm just not firing on all engines today...
I have a base class with a single ctor that takes an implementation of an interface as it's only parameter. I'm using a DI framework and have my component registrations all set up and working fine.
When I inherit from this base class, unless I pass in a value to the base constructor, I have to define a parameterless ctor, which bypasses the DI.
So right now I have:
public class MyObjectBase
{
IMyRequiredInterface _InterfaceImpl;
public MyObjectBase(IMyRequiredInterface interfaceImpl)
{
_InterfaceImpl = interfaceImpl;
}
...
}
public class AnotherObject : MyObjectBase
{
public AnotherObject()
{
}
...
}
So, out of the gate this fails. I get errors when AnotherObject is instantiated indicating that there is no base class ctor that takes 0 parameters. Ok, I get that. But now I have a choice: either modify the descendant class ctor to take a similar parameter and pass that value on to the base ctor, or wire up a ctor chain in the base class that forces me to bypass DI and create a concrete implementation of the required interface and pass it in as part of the parameterless ctor declaration.
The goal is to meet the requirement of the base class without the descendant classes knowing anything about it.
Maybe I'm going about this all wrong, but it's bugging me. Any thoughts on a better way to handle this? I feel like I've got to be missing something simple...
The correct approach is:
public class AnotherObject : MyObjectBase {
public AnotherObject(IMyRequiredInterface interfaceImpl) :
base(interfaceImpl) {
}
}
You specifically asked for an approach other than this approach. Why?
The goal is to meet the requirement of the base class without the descendant classes knowing anything about it.
That's generally the wrong thing to do. Why do you want to do it?
Update:
Based on your later comment, you should probably use (and configure your container to use) property injection instead of constructor injection. That will get you all of your requirements.
Err....the whole point of inheriting from MyObjectBase is that, as it were, you get the good and the bad, as far as the behaviour goes. If you can't create a MyObjectBase without an object implementing IMyRequiredInterface, you can't create a subclass without such an object either.
So what do you do when someone doesn't hand you that. Do you have a default?
It's quite reasonable for a subclass to instantiate something that implements IMyRequiredInterface, and pass that to the superclass constructor with a super(...) call. Can you do that? (Though, as I recall, you can get a bit hung up on this in Java, having to call super before doing anything else....)
There's a code smell here. If you inherit from a class that has a parameterless constructor it means that the author of this base class intended that it cannot function properly without supplying the necessary dependency. If you inherit from it and call a base method that required this dependency your code will probably fail if the dependency is not supplied. So if you really think that you should completely override this behavior you don't have to inherit from this base class, otherwise just copy the constructor in the inherited class.
What about providing a protected constructor in the base class that takes no paramters?
class MyBase
{
readonly int _x;
public MyBase(int x)
{
_x = x;
}
protected MyBase()
{
_x = 0;
}
}
class MyChild : MyBase
{
public MyChild()
{
}
}
Most DI frameworks have the functionality to inject services into properties (Property Setter Injection) using Attributes so you can try that.
You can subclass but the subclass will have to know how to create or get the Interface Implementation (using the ServiceLocator or something).
From the DI's point of view it doesn't have anything to fulfill because the class only has an empty constructor (most use the constructor with the most params) and no attributes telling him to do anything else.
I had the same scenario where my base (concrete) class and the child class had a dependency, I was worried if these are different instances.
But, Autofac (I believe other container tools too) has .InstancePerRequest() which will share the same instance per Http request.
builder.RegisterType().As().InstancePerRequest();