I'm finding myself unable to solve a design problem.
For the sake of my simplicity, I'm going to use C# (Web API).
Let's say I have an abstract class RestController
:
public abstract class RestController
{
// ... Irrelevant code here
protected virtual async Task<IHttpActionResult> UseAuthorization(HttpMethod method, Func<Task<IHttpActionResult>> operation)
{
return await operation();
}
protected virtual async Task<IHttpActionResult> UseHttpCache(Func<Task<IHttpActionResult>> operation)
{
return await operation();
}
// ... Irrelevant code here
}
These two methods would be overriden and reimplemented by child classes. Any class that would just want to extend from RestController
and don't want to use authorization or cache features, might just want to leave those methods untouched, as the default base implementation, does nothing.
Now, I was thinking of having something like this:
public abstract class CachedRestController : RestController
{
protected override async Task<IHttpActionResult> UseHttpCache(Func<Task<IHttpActionResult>> operation)
{
IHttpActionResult result = await operation();
return new HttpCachedResult(result);
}
}
public abstract class AuthenticatedRestController : RestController
{
protected override async Task<IHttpActionResult> UseAuthorization(HttpMethod method, Func<Task<IHttpActionResult>> operation)
{
return IsAuthenticated(method) ?
await operation() :
Unauthorized();
}
}
My goal is to achieve something similar to the following:
public class MyController : CachedRestController, AuthenticatedRestController
{
}
Adding or removing features (caching, authentication, etc.), would be as easy as adding or removing parent classes.
Unfortunately, as we all know, multiple inheritance is not supported in C#, so I can not go with that solution.
I'm looking for a good design pattern (C# compliant) that would more or less achieve what I'm looking for.
I know of the Decorator Design Pattern, but having a controller as a field pretty much scares me as I am responsible for creating it (the Web Api framework should be responsible for that).