I have an interface -though it could also be an abstract class- that should allow its implementers to specify whether they support a particular feature and I'm looking for the best way to achieve that.
There are several choices here:
Looking at BCL, I see that the Stream
class has properties like CanRead
and CanSeek
, which can be used to check if a feature is supported and throws a NotSupportedException
, if I do something that is not supported.
public interface IHandler
{
bool SupportsA { get; }
bool SupportsB { get; }
void A();
void B();
}
This would be an appropriate approach for me, though I have more than a few features that may or may not be supported and I prefer not to define a "SupportsX" property for each one.
I'm also very fond of bitwise Enum
values and I think that another way would be:
[Flags]
public enum HandlerFeature
{
None = 0
A = 1,
B = 2,
C = 4
}
public interface IHandler
{
HandlerFeature Features { get; }
void A();
void B();
void C();
}
And an extension method like this could be written:
bool Supports<T>(this T handler, HandlerFeature feature) where T : IHandler
Which I think would also be much prettier than the other approach but, I couldn't help but think that if every Enum
value would correspond a member in the contract, I should be able to mark those members more explicitly. Then I thought about attributes:
public interface IHandler
{
[HandlerRequires(Feature.None)]
HandlerFeature Features { get; }
[HandlerRequires(Feature.A)]
void A();
[HandlerRequires(Feature.B)]
void B();
[HandlerRequires(Feature.A | Feature.B)]
void AB();
[HandlerRequires(Feature.C)]
void C();
}
Although I don't know how to leverage an attribute like this in runtime, it definitely makes the interface definition looks explicit enough.
Is there a best-practice for this?
Or another approach you recommend?
Or anything wrong with the ones I specified?