1

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).

7

This seems like one of those common "favor composition over inheritance" scenarios. A RestController serves as an endpoint for REST calls. Not something to govern Authorization. Not something to control the HttpCache. It's a violation of the Single Responsibility Principle.

Instead, you should have classes (strategies if you'd prefer) to govern these two responsibilities. Then you can compose them as needed into other controllers.

  • Very good answer. You can compose a collection of objects with single responsibility for each. Say if you want authorization, all you do is add authorization manager to your collection. – Alexus Jun 26 '15 at 17:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.