这是来自外部库的代码,我无法控制:
public class Library {
public delegate void Handler<T>(in T type);
public void Subscribe<T>(Handler<T> handler) {
// Whatever...
}
}
这是我的应用代码:
public class Application {
public void Run() {
var library = new Library();
var types = new List<Type>() {typeof(int), typeof(string)};
foreach(var type in types) {
var methodLibrary = library.GetType().GetMethod("Subscribe");
var methodLibraryGeneric = methodLibrary.MakeGenericMethod(new Type[] {type});
var methodApplication = this.GetType().GetMethod("OnHandler", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var methodApplicationGeneric = methodApplication.MakeGenericMethod(new Type[] {type});
// [EXCEPTION] System.ArgumentException: method arguments are incompatible
var delegateApplication = Delegate.CreateDelegate(typeof(Library.Handler<>), methodApplicationGeneric);
methodLibraryGeneric.Invoke(library, new object[] {delegateApplication});
}
}
private void OnHandler<T>(in T type) {
// Whatever...
}
}
我希望这是清楚的,我想做的是:我有一大堆类型,我在运行时确定(不只是int/string演示目的),我希望他们都注册与外部库调用回我的代码。
作为一种解决方法,我可以为每种类型显式地调用library.Subscribe<int>(OnHandler)
,但这将是相当脆弱和易出错的,我认为泛型可以帮助。
您应该创建一个构造的委托类型Handler<Something>
的实例,而不是未绑定的Handler<>
。基本上,您应该在typeof(Handler<>)
上调用MakeGenericType
,就像您在两个方法上所做的那样。您还需要将this
传递给CreateDelegate
,因为methodApplicationGeneric
不是静态方法。
var delegateApplication = Delegate.CreateDelegate(
typeof(Library.Handler<>).MakeGenericType(type),
this,
methodApplicationGeneric
);