0

Lately I've been using this sort of pattern a lot:

abstract class myBaseClass
{
    //some common methods/properties/etc that all inheritors would share
    //some abstract methods/properties/etc that inheritors must implement

    protected abstract bool DoIHandleThisSortOfRequest(...);

    public static myBaseClass GetHandler()
    {
        // some reflection to enumerate through classes
        // that inherit from myBaseClass, and use
        // something like DoIHandleThisSortOfRequest() on each
    }
}

... and, I mean, the code is nice and neat... but it does mean I'm using reflection quite a bit.

For example, I'm currently working on a new process that works via command line than needs to handle a lot of different request types, and found myself using this sort of pattern, kinda like this:

abstract class FunctionRequest
{
    protected abstract string RequestName { get; }
    public abstract void Run();
    public static FunctionRequest GetHandler(string requestName)
    {
        // use reflection to get list of classes deriving from FunctionRequest
        // find one that has instance.RequestName equals requestName
    }
}
public class QueryRequest : FunctionRequest
{
    protected override string RequestName { get { return "Query"; } }
    public override void Run()
    {
        // ... code ...
    }
}

Is there a better way to structure this? I'm not too worried about the overhead of Reflection on this... but I realize if there's a better way to do it, I should get in the habit of doing it the right way :-)

Kevin
  • 2,133
  • 1
  • 9
  • 21
  • So `QueryRequest` and every other class derived from `FunctionQuest` has the `GetHandler` method? Seems weird to me. I would have just one `RequestHandler` class and then setup a `IRequest` interface with a public class `Request` that runs code specific to each request and inject the interface into the handler's constructor so that when the handler class is called to run a specific command it just executes the code based on an if statement. I would map each type of request in a struct or class of constants so the if conditions would like kinda like `if (request == Const.Query) { .. }` – Paul Carlton Jul 21 '17 at 19:25
  • Nah - the GetHandler isn't inherited by the derived classes, it's a static method of the base class (statics aren't inherited). So the usage would be something like: BaseClass handler = BaseClass.GetHandler("Query"); handler.Run(); (I'm greatly oversimplifying my code to make it minimal - it has to do stuff with command line args, etc.) – Kevin Jul 21 '17 at 19:31
  • I guess what I'm getting at is I don't see why you would need to use reflection in this context even though I get what you're saying. If you are worried about overhead and readability, I would instead line out each type of request explicitly (like a static class of constants) and have one larger request class that has methods for each different request or something close to that. So it's explicit what you're doing and you can easily see all the different request types in one place. I'll try and illustrate it below. – Paul Carlton Jul 21 '17 at 19:51

1 Answers1

1

I would prefer to do it this way. I'm not sure if what you are doing is "wrong" in your use case (maybe a high guru can help out with that) but if you are worried about the overhead of reflection (What is the "cost" of .NET reflection?) then it makes sense to code it explicitly like so:

public static class RequestTypeConst
{
    public const Query = "Query";
}

class Handler
{
    protected IRequest Request { get; set; }

    public Handler(IRequest request) 
    { 
        Request = request;
    }

    public void HandleRequest(string requestType)
    {
        if (requestType == RequestTypeConst.Query)
        {
            Request.Query();
        }
    }
}

interface IRequest
{
    List<string> Query();
}

class Request : IRequest
{
    public List<string> Query()
    {
        /** do something **/
        return new List<string>();
    }
}

var handler = new Handler(new Request());
hanlder.HandleRequest("Query");
Paul Carlton
  • 2,785
  • 2
  • 24
  • 42
  • If I'm understanding your response, it'd involve putting the code for every request in the same class - the Request class? I'm really disinclined to do that - it'd make my class into a sort of God Class that would handle every single type of request. Maybe I should think about the constants, but instead handing off a function within a god class, hand off a class instead. Hmmm.... I'll give that some thought. – Kevin Jul 24 '17 at 13:48
  • Well you could abstract it as you wish if you don't want a "god" class. I'd say "main" class. But the point is that it's explicit. I'm not sure how compartmentalized the end goal of the application is but if there are requests that can be grouped into specific types of requests, then break up the class into those, and inject them into the request handler. IE: `NewsRequest()`, `CommentRequest()`, etc... – Paul Carlton Jul 24 '17 at 18:40