簡體   English   中英

C#反射獲取某個類的所有子類並用它們的類型調用泛型方法

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

我有數據包:

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

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

我有一個像這樣的通用抽象“處理程序”類:

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

和他們的實現:

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!");
    }
}

我需要像這樣注冊它們:

        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); });

這是 SubscribeReusable 方法:

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

問題是,隨着解決方案的增長,我將不得不繼續添加這些調用。

我想知道是否可以使用反射來動態調用“SubscribeReusable”。 我面臨的問題是泛型。

這是我開始的代碼:

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

我被困的地方

我試過 Type 和 dynamic,但還是不行。 我想知道我是否有正確的方法。

 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()
                    });
                }
            }

錯誤

編輯:我已經根據亞歷山大給出的答案更新了代碼:

    private void RegisterPacketHandlers()
    {
        Console.WriteLine("Using reflection to subscribe handlers...");
        
        var baseType = typeof(PacketHandler<>);
        var assembly = baseType.Assembly;
        foreach (var derivedType in assembly.GetTypes()
            .Where(t => !t.IsAbstract &&
                        !t.IsInterface &&
                        t.BaseType != null &&
                        t.BaseType.IsGenericType &&
                        t.BaseType.GetGenericTypeDefinition() == baseType))
        {
            
            Console.WriteLine("Found class with type : " + derivedType.FullName);

            //

            try
            {
                
                // TODO Generate a delegate and hook into your processor

                var mi = derivedType.GetMethod("Handle");
                var action = DelegateBuilder.BuildDelegate<Action<object, int>>(mi);

                _netPacketProcessor.SubscribeReusable(action);
            }
            catch (Exception e)
            {
                Console.WriteLine("Error : " + e);
            }
        }
    }

我仍在嘗試使用派生類型調用 SubscribeReusable

對於問題的第一部分,您可以使用以下代碼段獲取PacketHandler<T>所有直接子項:

var baseType = typeof(PacketHandler<>);
var assembly = baseType.Assembly;
foreach (var derivedType in assembly.GetTypes()
    .Where(t => !t.IsAbstract && 
                !t.IsInterface && 
                t.BaseType != null && 
                t.BaseType.IsGenericType && 
                t.BaseType.GetGenericTypeDefinition() == baseType))
{
    // TODO Generate a delegate and hook into your processor
}

第二部分(調用委托)可以使用這里的方法解決。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM