mardi 22 septembre 2020

C# reflection get all subclasses of certain class and call generic method with their type

I have packets :

public class HelloPacket
{
    public string MyName { get; set; }
}

public class PingPacket
{
    public float PingTime { get; set; }
}

I have a generic abstract 'handler' class like this :

public abstract class PacketHandler<T>
{
    public abstract void Handle(T t);
}

And their implementations :

public class HelloPacketHandler : PacketHandler<HelloPacket>
{
    public override void Handle(HelloPacket helloPacket)
    {
        Console.WriteLine("Received Hello packet!");
    }
}

public class PingPacketHandler : PacketHandler<PingPacket>
{
    public override void Handle(PingPacket pingPacket)
    {
        Console.WriteLine("Pong!");
    }
}

I need to register them like this :

        NetPacketProcessor _netPacketProcessor = new NetPacketProcessor();

        HelloPacketHandler helloHandler = new HelloPacketHandler();
        PingPacketHandler pingHandler = new PingPacketHandler();

        _netPacketProcessor.SubscribeReusable<HelloPacket>((packet) => { helloHandler.Handle(packet); });
        _netPacketProcessor.SubscribeReusable<PingPacket>((packet) => { pingHandler.Handle(packet); });

Here is the SubscribeReusable method :

public void SubscribeReusable<T>(Action<T> onReceive) where T : class, new()
{
}

The problem is that, as the solution grows, I will have to keep adding these calls.

I'm wondering if I could use reflection to dynamically call 'SubscribeReusable'. The problem I'm facing is with the generics.

Here is the code I started with :

        foreach (Type i in typeof(PacketHandler).Assembly.GetTypes())
        {
            if (typeof(PacketHandler).IsAssignableFrom(i) && !i.IsAbstract && !i.IsInterface)
            {
                // Subscribe here
            }
        }

Where I'm stuck

I tried Type and dynamic, but it is still not working. I'm wondering if I even have the right approach.

 foreach (dynamic i in typeof(PacketHandler<dynamic>).Assembly.GetTypes())
            {
                if (typeof(PacketHandler<dynamic>).IsAssignableFrom(i) &&
                    !i.IsAbstract && !i.IsInterface)
                {
                    PacketHandler<dynamic> pkt = (PacketHandler<dynamic>) Activator.CreateInstance(i);

                    Type t = pkt.GetType();

                    MethodInfo method = typeof(NetPacketProcessor).GetMethod(nameof(NetPacketProcessor.SubscribeReusable));
                    MethodInfo generic = method.MakeGenericMethod(t);
                    generic.Invoke(this, new object[]
                    {
                        pkt.Handle()
                    });
                }
            }

Error





Aucun commentaire:

Enregistrer un commentaire