0

I'm trying to simplify a Send function on a server I'm building. I'd like to reduce the number of methods that send data by having it so the sent information is specified in the parameters.

For example, going from lots of methods like this:

    public static void QueryUsername( string text )
    {
        PacketBuffer buffer = new PacketBuffer();

        buffer.Write( Outbound.DoesUserExist );
        buffer.Write( text );
        ClientTCP.SendData( buffer.ToArray() );
        buffer.Dispose();
    }

To a single method like this:

    public static void Send( Outbound packageIndex, params object[] parameter )
    {
        PacketBuffer buffer = new PacketBuffer();
        buffer.Write( packageIndex );

        foreach ( object item in parameter )
        {
            buffer.Write( item );
        }

        ClientTCP.SendData( buffer.ToArray() );
        buffer.Dispose();
    }

I'm having difficulty figuring out how to pass the parameter data through the Write method though.

Anyone have any suggestions on how I can achieve this?

The Write method has 5 overloads that transform different types into bytes so they can be packaged and sent between the client and server.

Anthony
  • 301
  • 1
  • 2
  • 13

1 Answers1

1

To do exactly what you are asking, you will need to use reflection to look up the appropriate method, based on the type of the provided argument(s). See e.g. How can I programmatically do method overload resolution in C#?.

Note that reflection is very slow. If you're going to take this route, you will probably want to at least memoize the MethodInfo object for each parameter type you come across, and more likely you'll want to memoize an actual delegate instance representing the method (e.g. using Expression to build the delegate).

An alternative approach would be to create the dictionary of delegates manually in code. This is a far simpler way to achieve the goal, but runs the risk of overlooking a supported method. You'll need to make sure your dictionary contains entries for every parameter type you expect, and if a new type is added later, you'll have to remember to add it to your dictionary.

All that said, I'd advise against doing it this way. I don't know how many methods you have right now, but the fact is that they accurately reflect the complexity of your network API. It is easy to look at the code and see everything that your protocol supports, just by looking at the methods that have been implemented. It's also trivial to both see what the parameters for each protocol method are, and perhaps most importantly, the C# type system provides you with compile time guarantees of the correctness of each call site.

If you switch to a reflection-based approach, you will lose all of these features that improve the maintainability and reliability of the code. Each caller will be expected to just "know" the correct parameters to pass, and you'll get no help from the compiler to ensure that they pass the right ones. And the code will be harder to read as well.

If you are finding the number of methods in your API exceed some threshold of comfort, you may want to consider whether the API itself needs to be redesigned, either by adding new endpoints, or by structuring the methods in the API to includes some kind of hierarchy that helps organize them better. I'm not convinced that changing the implementation of the API is the right path. Indeed, I'm pretty sure it's not. :)

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136