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.

4

1 回答 1

2

我会创建一个接口,我们称之为

public interface ICommandManager
{
    ReturnPacket DoYourStuff();
}

和这样的属性:

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

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

您现在可以为您的命令处理实现类并为它们提供必要的属性。

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

现在,您可以使用例如 Reflection 来初始化这些类的对象(只需查找实现的类型ICommandManager),而无需对 a 进行硬编码,只需在有新命令时switch创建新实现即可。ICommandManager

或者更花哨的方式,没有使用Ninject的属性:

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

现在您可以使用Ninject来解决您的问题。使用此代码注册您的绑定。

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

稍后您可以使用以下方法解决此问题:

kernel.Get<ICommandManager>(metadata => 
    packet.Command == metadata.Get<Command>("Command"));
于 2013-05-24T05:35:51.870 回答