2

First, a bit of background of my question; I am writing a modular Server/Client type program in C#. I have a threaded processing system to handle my packets from a client queue, an example of what I am working with:

public delegate object ProcessPacket(object data);
public class QueueHandler
{
    //Awesome functions/variables
    private void Proccess()
    {
        object retPacket = client.ProcessPacket(obj);
        NetworkCommon.Sendpacket(retPacket, _clientSocket);
    }
    //Even more awesome functions.
}
//Client ProcessPacket delegate
private static object ProcessPacket(object packet)
{
    ReturnPacket ret = new ReturnPacket();
    switch (packet.Command)
    {
        case Command.Login:
            //Do login stuff
            break;
        case Command.Foo;
            //Foo stuff
            break;
        case Command.Bar;
            //Bar stuff
            break;
        default:
            ret.Responce = CommandResponce.CommandNotRecognized;
    }
    return ret;
}

As you can guess, this isn't very extensible, and will be hard to manage with feature additions. My question is, What is a more practical way of this?

I thought of a List<string,TProcessCommand> of sorts, assigning a custom attribute to the function then building that list on start up using reflection. But feel that may still be cumbersome to manage and possibly unneeded processing power each start up.

Another option I have considered is using the MEF, but I am having a hard time wrapping my head around how to identify between the commands without using Linq, which I am unfamiliar with.

[[EDIT]] I just noticed in a MEF example, the ExportMetadataAttribute was used. I will give this a shot with my code.

Patrick S
  • 21
  • 2
  • The post seems less relevant with linq, but linq is definitely tool you should have as a C# programmer. – David May 24 '13 at 02:59
  • Refactrong `swtich` into more extendable code is very common question - search for it (i.e. on SO - http://stackoverflow.com/search?q=%5Bc%23%5Dswitch+refactoring) to see more alternatives. Inheritance and Dictionary of command to action mapping are common options. – Alexei Levenkov May 24 '13 at 03:35

1 Answers1

2

I would create an interface, let's call it

public interface ICommandManager
{
    ReturnPacket DoYourStuff();
}

and an Attribute like this:

public class HandlesAttribute : Attribute
{
    public Command HandlesCommand { get; private set; }

    public HandlesAttribute(Command cmd)
    {
        this.HandlesCommand = cmd;
    }
}

You can now implement classes for your command handling and give them the necessary Attribute.

[Handles(Command.Login)]
public class LoginCommandManager : ICommandManager
{
    public ReturnPacket DoYourStuff()
    {
        var ret = new ReturnPacket();
        /* Do some stuff */
        return ret;
    }
}

Now you can initiliaze objects of those classes with e.g. Reflection (just look for types, that implement ICommandManager), without hardcoding a switch and just by creating a new ICommandManager implementation when there is a new command.

Or a little more fancy way, without attributes using Ninject:

public class LoginCommandManager : ICommandManager
{
    public ReturnPacket DoYourStuff()
    {
        var ret = new ReturnPacket();
        /* Do some stuff */
        return ret;
    }
}

Now you can use Ninject to resolve your problem. Use this code to register your bindings.

kernel.Bind<ICommandManager>()
    .To<LoginCommandManager>()
    .WithMetadata("Command", Command.Login);
/* ... */

And later you can resolve this with:

kernel.Get<ICommandManager>(metadata => 
    packet.Command == metadata.Get<Command>("Command"));
Jan P.
  • 3,261
  • 19
  • 26