首页 > 解决方案 > 如何调用通用委托?

问题描述

这是来自我无法控制的外部库的代码:

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)每种类型,但这会相当脆弱且容易出错,而且我认为泛型可以提供帮助。

标签: c#genericsreflectiondelegates

解决方案


您应该创建构造委托类型的实例Handler<Something>,而不是未绑定的Handler<>。基本上,您应该调用MakeGenericTypeon typeof(Handler<>),就像您对这两种方法所做的那样。您还需要传递thisto CreateDelegate,因为methodApplicationGeneric它不是静态方法。

var delegateApplication = Delegate.CreateDelegate(
    typeof(Library.Handler<>).MakeGenericType(type),
    this,
    methodApplicationGeneric
);

推荐阅读