【问题标题】:Dynamically invoke a method given a Type variable动态调用给定类型变量的方法
【发布时间】:2018-05-20 22:04:13
【问题描述】:

我的目标: 我有一个系统,我希望其他人能够添加一个 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??!

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

【问题讨论】:

  • 在我看来您正在寻找Type selectedType = Type.GetType(fullTypeNameAsString); - 然后您在解决方案 1 中已经拥有什么?解决方案 1 现在会发生什么?另外:TheInterfaceMethod 是实例方法吗?还是静态方法?如果是实例方法:它应该使用什么对象?如果是静态方法:将null传递给第一个参数
  • 您的选择列表可以包含实际对象吗?将显示的名称放在通用界面上而不是枚举上。然后,您可以直接从所选对象调用该方法。
  • @user6144226 不错;如果这些对象实际上在List<ISomeInterface> 中,您可以只使用theList[(int)enumValue].TheInterfaceMethod();
  • 你为什么用MakeGenericMethod,是接口Generic中的方法吗?
  • 您创建这些类可以调用这些方法的频率是多少?

标签: c# .net unity3d


【解决方案1】:

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

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

    interface IInterfaceWithGenericMethod
    {
        void TheInterfaceMethod<T>();
    }

这是一个使用变量的示例:

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

有趣的是,一旦有了对象的实例,就不再需要反射来调用该方法了。您可以简单地将其转换为您的界面。假设您的接口名为 IAwesomeInterface:

        Type selectedType = typeSelectedByEnum;
        object obj = Activator.CreateInstance(selectedType);
        IAwesomeInterface converted = obj as IAwesomeInterface;
        converted.TheInterfaceMethod();

【讨论】:

  • 活化剂是我要找的!是的,我知道接口不是静态的,所以 method.Invoke(null,null) 不起作用并一直挂在对象位上。这行得通,谢谢。
  • 如果你使用反射,有接口有什么意义?这个答案与界面的目的完全矛盾。
  • 顺便说一句,你可以只做 IInterface interf = go.GetComponent(); if (interf!= null)interf.TheMethod();
猜你喜欢
  • 2016-07-26
  • 2011-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-14
  • 2017-04-16
  • 1970-01-01
相关资源
最近更新 更多