给定类型变量动态调用方法

Fir*_*tGI 5 .net c# unity-game-engine

我的目标: 我有一个系统,我希望其他人能够添加一个包含特定方法的 C# 脚本,我可以在运行时从另一个类中查找和执行该方法。

我的方法: 我创建了一个带有方法的接口,因此我可以遍历任何使用反射实现该接口的类并列出它们,然后使所有这些类之间的方法名称相同。

我有一个类,它包含在查找过程中找到的所有类的枚举,用户可以在运行时在它们之间进行选择。

我现在需要能够获取所选类类型的方法并调用它的方法,问题是我肯定知道方法的名称,但类的类型存储为变量。

编码:

//来自内存的伪代码:

            //Possible solution 1:
            Type selectedType = typeSelectedByEnum;
            MethodInfo genericMethod = selectedType.GetMethod("TheInterfaceMethod").MakeGenericMethod(selectedType);
            genericMethod.Invoke(selectedType, new object[0]);

            //Possible solution 2: (however I would much prefer to use something avaliable prior to .NET 4.6)
            Type selectedType = typeSelectedByEnum;
            dynamic changedObj = Convert.ChangeType(selectedType, selectedType);//-Something here needs to implement IConvertable, how would I set this up?
            changedObj.TheInterfaceMethod();

            //Possible solution 3:

            //Your solution??!
Run Code Online (Sandbox Code Playgroud)

感谢任何帮助,在这一点上,我已经尝试了很多东西,并且对任何可能的运行时替代方案持开放态度。如有必要,我可以提供更多代码。

小智 5

由于您使用接口来标记具有您的方法“TheInterfaceMethod”的类,因此该方法不能是静态的。这意味着您需要一个对象的实例来调用该方法。该激活器类提供了一种简单的方法来创建对象的实例,但它确实需要(在你的情况很可能是一个公共的构造函数),能见度默认构造函数。

我还注意到您的示例存在潜在问题,即您正在调用“MakeGenericMethod”。仅当函数具有一些您需要定义以获得有意义的函数的泛型类型参数时才需要这样做。比如这个界面:

    interface IInterfaceWithGenericMethod
    {
        void TheInterfaceMethod<T>();
    }
Run Code Online (Sandbox Code Playgroud)

这是使用您的变量的示例:

        Type selectedType = typeSelectedByEnum;
        MethodInfo method = selectedType.GetMethod("TheInterfaceMethod");
        object obj = Activator.CreateInstance(selectedType);
        method.Invoke(obj, null);
Run Code Online (Sandbox Code Playgroud)

有趣的是,一旦拥有对象的实例,就不再需要反射来调用该方法。您可以简单地将其投射到您的界面。让我们假设您的接口称为 IAwesomeInterface:

        Type selectedType = typeSelectedByEnum;
        object obj = Activator.CreateInstance(selectedType);
        IAwesomeInterface converted = obj as IAwesomeInterface;
        converted.TheInterfaceMethod();
Run Code Online (Sandbox Code Playgroud)