C# reflectin:为给定的类实例调用具有泛型类型和泛型参数的方法



我需要使用反射调用泛型参数的泛型方法,其中泛型类型作为字符串中的参数提供。网上有一些泛型和反思的例子,但我仍然无法让它工作。

无需反思:

string typeName = "EventType"; // as param1 -> type name
string content = ""; //as param2 -> some json cotnent
IMyBus bus = new MyBus();
switch (typeName)
{
case "EventType":
IEventType content = Deserialize<IEventType>(content);
bus.Publish<IEventType>(content);
break;
case "EventType2":
IEventType2 content2 = Deserialize<IEventType2>(content);
bus.Publish<IEventType2>(content2);
break;
}

相反,我想使用反射重写它以提供更多的事件类型,而无需重写此特定代码。

以下是我的测试类:

public interface IMyBus **//TWO METHODS HERE, WE NEED TO CALL FIRST ONE!**
{
void Publish<T>(T message, CancellationToken cancellationToken = default(CancellationToken)) where T : class; //THIS SHOULD BE CALLED
void Publish<T>(T message, int i, CancellationToken cancellationToken = default(CancellationToken)) where T : class;
}
// Interface implementation
public class MyBus : IMyBus
{
public void Publish<T>(T message, CancellationToken cancellationToken = default(CancellationToken)) where T : class
{  ... }
public void Publish<T>(T message, int i, CancellationToken cancellationToken = default(CancellationToken)) where T : class
{  ... }
}
public interface IEventType { int forTest { get; set; } }
public class EventType : IEventType { public int forTest { get; set; } }
public interface IEventType2 { int forTest2 { get; set; } }
public class EventType2 : IEventType2 { public int forTest2 { get; set; } }

这是我已经尝试过的:

IMyBus bus = new MyBus();
EventType content = new EventType() { forTest = 1 };
var eventTypeName = $"ConsoleApp.EventType";
var iEventTypeName = $"ConsoleApp.IEventType";
Type intEvType = Type.GetType(iEventTypeName);
Type evType = Type.GetType(eventTypeName);
MethodInfo openGenericMethod = typeof(IMyBus).GetMethod("Publish", 2, new Type[] { intEvType, typeof(CancellationToken) });
MethodInfo closedGenericMethod = openGenericMethod.MakeGenericMethod(evType);
object o2 = closedGenericMethod.Invoke(bus, new object[] { content });

但这是错误的。openGenericMethod始终为空。

我认为在这种情况下,最好根据名称和参数数量手动查找方法:


MethodInfo openGenericMethod = typeof(IMyBus).GetMethods()
.SingleOrDefault(m => m.Name == "Publish" 
&& m.IsGenericMethod 
&& m.GetParameters().Count() == 2);

但是您将使用optional参数调用方法。这就是为什么你应该使用其他Invoke方法,你可以在其中定义绑定标志:

MethodInfo closedGenericMethod = openGenericMethod.MakeGenericMethod(evType);
closedGenericMethod.Invoke(bus, BindingFlags.OptionalParamBinding, null, 
new object[] { content, Type.Missing }, CultureInfo.InvariantCulture);

我已经在测试控制台应用程序中对其进行了测试。它有效。

最新更新