4

I'm struggling with this new to me Delegates + Handlers thing. It seems the right solution for me, but I can't tie everything up.

Will try my best to explain what I want to achieve.

First of all, I'm using .NET 4.0 Framework + Photon Server (For multiplayer games) (There's no need in Photon experience in order to answer me)

So actually, what happens right now, is that the client (a game) sends operation to my server, which I must recognize and call a certain function on my server according to the operation code that I receive.

Here's how it looks right now:

switch (operationRequest.OperationCode)
        {
            case 1:
                if (operationRequest.Parameters.ContainsKey(1))
                {
                    Log.Debug("Received: " + operationRequest.Parameters[1]);

                    OperationResponse response = new OperationResponse(operationRequest.OperationCode);
                    response.Parameters = new Dictionary<byte, object> {{1, "Response Received"}};
                    SendOperationResponse(response, sendParameters);
                    Flush();
                }
                break;
        }

This actually works fine for me. But, I know for sure there will be like 200+ operation codes. Not really nice to switch all of them, It's better to call a function (handler) that is assigned to that Operation Code.

According to my knowledge, here where delegate comes handy.

I want to have a Dictonary, that stores "byte,Handler"

 where "byte" is operation code

 where "Handler" is a delegate to the function

Something like that I assume:

byte operationCode = operationRequest.OperationCode; 

if(dictionary.ContainsKey((operaionCode)) {
    dictionary[operationCode](someArguments);
}

From this point, I'm totally confused.

How to create such Dictionary, how to create handlers, assuming that I want to store them in different classes, how to delegate them and store in a dictionary.

Here's what my friend suggested me (and then vanished for one week, so I can't ask him again):

  1. Create a dictionary

    Dictionary<byte, name> = new Dictionary<byte, name>();
    
  2. Add handlers to that dictionary

    dict.Add(operationCode, MoveUnit);
    
  3. Initialize delegates (Where!?)

    ???
    
  4. Define your handlers

    private void MoveUnit(SendParameters sendParameter) {...}
    

If.. anyone, by any chance, got the idea, please assist me.

Thanks to everyone for time spent on reading this. :|

deb0rian
  • 966
  • 1
  • 13
  • 37

1 Answers1

3

Assuming all the methods take a SendParameters, then you really want:

private static readonly Dictionary<int, Action<SendParameters>> Actions = 
    new Dictionary<int, Action<SendParameters>>
{
    { 1, MoveUnit },
    { 2, AttackUnit }
};

...

static void HandleRequest(Request request)
{
    Action<SendParameters> action;
    if (Actions.TryGetValue(request.OperationCode, out action))
    {
        action(request.Parameters);
    }
}

static void MoveUnit(SendParameters parameters)
{
}

static void AttackUnit(SendParameters parameters)
{
}

It gets slightly trickier for instance methods - the static dictionary doesn't know about instances, so it may make sense to make the action take the instance. Assuming this in a class called Foo, you might want something like:

private static readonly Dictionary<int, Action<Foo, SendParameters>> Actions = 
    new Dictionary<int, Action<Foo, SendParameters>>
{
    { 1, (foo, parameters) => foo.MoveUnit(parameters) },
    { 2, (foo, parameters) => foo.AttackUnit(parameters) }
};

private void MoveUnit(SendParameters parameters)
{
}

It's a bit uglier, admittedly... you really want to be able to build delegates which implicitly take "this" as the first parameter. There are ways of doing that, but they're a bit more complicated.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Holy sh... It actually made sense. A huge thanks to you, Mister! The only question is: If I have a lot of instances, say, for each function(handler) I have a separate class that does all the logic for that function. Then "Action(Foo, SendParameters)" is useless, right? I can store instance name in enum that is associated to the operation code. And yes, all methods take SendParameters – deb0rian May 29 '12 at 21:10
  • @Fratyr: It's not really clear to me what your situation is, I'm afraid. But you'd have to have *some* way of getting to the right instance. I wouldn't use *names* though. – Jon Skeet May 29 '12 at 21:16
  • I actually don't have a situation yet, and yes, you got it straight to my problem, with a little offset. The whole thing I've explained above, describes my tries to design the right way to operate a lot of handlers, without flooding my class with a huge switch selector, but instead, have a separate method, maybe class, for each operation that comes from the client. because, you may assume, that the same "MoveUnit" function has a lot of calculations to do, so for the sake of readability it must reside in another class. Your example is great, it just lacks the ability for multi classes. :) – deb0rian May 29 '12 at 21:25