Reputation: 30728
How to put constraint on constructor parameters?
Is it a good practice?
I have an interface, and I would require Logger component (to be injected by unity).
How can it be enforced that all derived classes would have Logger component (ILogger) as a parameter?
I could not find any appropriate solution.
Only workaround I have found is to put method Initialize (<parameters>)
in the interface. This is an ugly approach, and requires special handling.
Is there any design pattern that address such problems?
Upvotes: 0
Views: 1569
Reputation: 4751
Why would you ever want to force such a thing?
Focus on what is the real contract (defined by an interface), not on such an unimportant thing like logging. The contract should be defined in a way, that you can't remove any method/property without loosing the ability to perform core functionality.
For instance if you have an interface:
interface IAdder
{
double Add(double first, double second);
}
Adding is the core functionality. You could have a third argument ILogger, but without it you can still add. Logging is the implementation detail, which should never be a part of a cotract.
Upvotes: 0
Reputation: 34325
You don't need a constraint to force derived classes to have a logger component. Just define the base class constructor to take an ILogger.
public class Foo
{
public Foo (ILogger logger) { /* some implementation here */ }
}
public class Bar : Foo
{
public Bar(ILogger logger)
: base(logger)
{
// some implementation here
}
}
Since Bar derives from Foo, it is forced to use the constructor that takes a logger. You can also make Foo abstract, which would force a user to create an instance of a derived class instead of Foo itself.
When you need to define an interface, don't just consider a C# interface. Abstract classes are perfect for cases like this. It is common to think of abstract classes as interfaces (not a C# interface). What you're asking can't be done with a C# interface because those define contracts, not implementation.
Upvotes: 3