Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Complex Function and type delegates in C#

I am a novice/intermediate C# developer trying to accomplish a task I would be comfortable doing in C.

Basically, I'm getting XML requests that I need to respond to with a corresponding response. The request/response pairs are well defined in a structure like:

  • "Method1Request" receives "Method1Response"
  • "Method2Request" receives "Method2Response"
  • ...

So, I'm going to create functions in my class called "Method1", "Method2",... that take parameters "Method1Request", "Method2Request",... and return "Method1Response", "Method2Response",...

In code, the function declarations would look like this, and the accompanying code is varied:

  • Mtehod1Response Method1(Method1Request);
  • Method2Response Method2(Method2Request);
  • ...

All of the function responses will immediately be serialized into XML, so, theoretically, the functions could all be like this, and could write the result to the private string variable "response": void Method1(Method1Request) void Method2(Method2Request) ...

Anyway, what I would like to do is "sample" the XML (already have this working), to find out what type of request it is and use a case statement to, essentially, run the appropriate function on the request and , therefore, generate the correct response.

So, I need to create a function that does all of the steps that remain the same around calling those specific functions. It would basically be structured like this (!PSEUDO CODE!):

void ProcessRequestResponse(Type RequestType, Type ResponseType, Method MethodToRun)
{
    ...create serializers for RequestType and ResponseType...
    ...deserialize XML into RequestType...
    [ResponseType] [MethodToRun]([RequestType]);
    ...serialize ResponseType into XML...
    ...store XML as variable in class...
}

I just have no idea how to actually create that function and have it know what function to run with which types. I looked into using the delegate "Func" methods, but I don't see a way to define them with types that are unknown at the time of creation.

Any direction on how to solve this would be appreciated. I don't think I need to type all of that code for each of my 15+ cases (hopefully!) and manage near identical instances of the almost same code.

like image 968
mobrien118 Avatar asked Jan 31 '26 11:01

mobrien118


1 Answers

I would go the Generics route, implementing some helper class and resolving the request-handling strategy using a configuration object (can be a simple Dictionary).

If you have 15+ request types, I would prefer having 15+ alternative classes, each implementing the corresponding handling strategy.

WARNING: just some throwaway example code, but should give you an head start.

// Define a weakly typed interface, to be called
// by the invoking code.
public interface IRequestHandler
{
  public string HandleRequest(string xmlRequest);
}

// Defines a generic handler, accepting two type parameters, one
// for the request, one for the response.
public abstract class RequestHandler<RequestType, ResponseType> : IRequestHandler
{

  public XmlSerializer GetRequestSerializer()
  {
    return GetSerializer(typeof(RequestType));
  }

  public XmlSerializer GetResponseSerializer()
  {
    return GetSerializer(typeof(ResponseType));
    // an alternative, depending upon your deserialization library,
    // could be:
    // return GetSerializer<ResponseType>();
  }

  public XmlSerializer GetSerializer(Type dataType)
  {
    ... resolve based on type.
  }

  public string HandleRequest(string xmlRequest)
  {
    if (request == null) throw new ArgumentNullException("request");

    var requestSerializer = GetRequestSerializer();
    var typedRequest = requestSerializer.Deserialize(xmlRequest) as RequestType;
    // response is a ResponseType
    var response = ProcessRequest(typedRequest);

    var responseSerializer = GetResponseSerializer();

    return responseSerializer.Serialize(response);
  }

  protected abstract ResponseType ProcessRequest(RequestType request);
}

// One handler implementation
// you can just declare the class and RequestHandler inheritance,
// and then right click and ask Visual Studio to "Implement abstract members"
public class ActualRequestHandler : RequestHandler<ActualRequest, ActualResponse>
{
  protected ActualResponse ProcessRequest(ActualRequest request)
  {
    // ... do your processing
  }
}

// One handler implementation
public class AnotherRequestHandler : RequestHandler<AnotherRequest, AnotherResponse>
{
  protected AnotherResponse ProcessRequest(AnotherRequest request)
  {
    // ... do your processing
  }
}

A simple configuration could be a static dictionary in your external processor class:

private static readonly Dictionary<Type, Func<IRequestHandler>> _strategyGetter = new Dictionary<Type, IRequestHandler>()
{
  {typeof(ActualRequest), () => new ActualRequestHandler()},
  {typeof(AnotherRequest), () => new AnotherRequestHandler()}
};

And finally, your global code:

Type requestType = ... your existing code processing the string request ...
Func<IRequestHandler> handlerFactoryMethod;
if(_strategyGetters.TryGetValue(requestType, out handlerFactoryMethod))
{
  var handler = handlerFactoryMethod();
  var responseString = handler(request);

  // ... do what you want with responseString ...
}
else
{
  // seems the request was not recognized.
}
like image 198
A. Chiesa Avatar answered Feb 03 '26 00:02

A. Chiesa