1

I'm designing a game in C#, I'm sure you get it a lot - but my question is a bit different in that I want to design something around an observer pattern to my understanding - and I can't find much information it.

All of my packets implement a basic interface, called IPacket... and I was hoping to fire off an event when a packet of a certain type was recieved; without using a massive switch.

I was perhaps hoping for something like:

networkEvents.PacketRecieved += [...]

Could anyone point me in the direction to do this?

1 Answers1

5

What about something like this:

public interface IPacket
{

}

public class FooPacket: IPacket {}

public class PacketService
{
    private static readonly ConcurrentDictionary<Type, Action<IPacket>> _Handlers = new ConcurrentDictionary<Type, Action<IPacket>>(new Dictionary<Type, Action<IPacket>>());

    public static void RegisterPacket<T>(Action<T> handler)
        where T: IPacket
    {
        _Handlers[typeof (T)] = packet => handler((T) packet);
    }

    private void ProcessReceivedPacket(IPacket packet)
    {
        Action<IPacket> handler;
        if (!_Handlers.TryGetValue(packet.GetType(), out handler))
        {
            // Error handling here. No packet handler exists for this type of packet.
            return;
        }
        handler(packet);
    }
}

class Program
{
    private static PacketService _PacketService = new PacketService();
    static void Main(string[] args)
    {
        PacketService.RegisterPacket<FooPacket>(HandleFooPacket);
    }

    public static void HandleFooPacket(FooPacket packet)
    {
        // Do something with the packet
    }
}

Each type of package you create registers a handler specific to that type of packet. Using a ConcurrentDictionary makes locking superfluous.

Henning Krause
  • 5,302
  • 3
  • 24
  • 37
  • Well, that goes over my head a little.. I can see you're creating a mapping of all the different packets, and presumably I'm reconstructing my packet object on the client side - and feeding it into the the processor. By calling a processRecievedPacket on it? What exactly is the way of having an external listener trigger, then? And listen? – Vaughan Hilts Oct 22 '11 at 21:16
  • Well, you are receiving binary data over a network connection. At some point you reconstruct them into .NET objects. You can now hand this packet off to the PacketService ProcessReceivedPacket method which selects the final handler for the packet. Isn't that what you intended? – Henning Krause Oct 22 '11 at 21:19
  • That is the intention - I'm just confused as to how my listener can 'hear' this event being triggered off. I'm still a novice in the subject, and I'm used to subscribing to an event.. and there's no event to subscribe to here. – Vaughan Hilts Oct 22 '11 at 21:23
  • No events are used in this implementation. But you register a handler for each packet using the RegisterPacket method. I'll update the example... – Henning Krause Oct 22 '11 at 21:27
  • I think I've got it now actually, I just register an 'Action' by hand for each event. – Vaughan Hilts Oct 22 '11 at 21:29
  • I've got it 100% now - thanks a lot! And I now understand the usage behind Action much clearer. – Vaughan Hilts Oct 22 '11 at 21:34