![](/img/trans.png)
[英]Get class from Type with Reflection and call a generic constructor with Type in 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.