如何从Type或其派生类型中调用方法?

时间:2014-03-12 23:50:49

标签: c# monodevelop

我正在尝试复制Unity 3D引擎的MonoBehaviour。我在Linux上使用monodevelop,大多数测试将在Windows中完成。

有关MonoBehavior.Start的更多信息,请参阅here

我想在从MonoBehavior继承的所有类型上调用Start方法。

这就是我的尝试:

class MonoBehaviour
{
  static Type[] types = Assembly.GetExecutingAssembly().GetTypes();

  public static void Main ()
  {
    foreach (Type type in types)
    {
      if (type.IsSubclassOf(typeof(MonoBehaviour)))
      {
        MethodInfo minfo = type.GetMethod ("Start");
        mInfo.Invoke (type, null); // This throws
      }
    }
  }
}

class example : MonoBehaviour
{
  void Start()
  {
    // I want this to be run from MonoBehaviour
    Console.WriteLine ("HelloWorld");
  }
}

class example1 : MonoBehaviour
{
}

2 个答案:

答案 0 :(得分:1)

编辑完全重做这个答案,因为现在我相信我知道你在问什么。

我将为您提供代码,允许您在程序集中调用Type的每个对象的Start。但是,我不认为这是MonoBehavior的工作原理。还有更多要考虑的问题。例如,应首先调用Awake,并且存在是否已启用脚本的条件。此外,我不认为这个方法一次被调用所有对象,但也许只有在创建/启动对象时。我没有Unity 3D体验,所以我对这些细节一无所知。我只依赖于你从问题中的链接中读到的内容。

我添加了一些额外的绑定标志,以表明这可以找到各种范围的方法。此外,在我的代码中,我明确地寻找没有参数的Start方法。这可以根据您的需要和喜好进行修改。

using System;
using System.Reflection;
class Program
{
  static void Main(string[] args)
  {
    Assembly asm = Assembly.GetExecutingAssembly();
    Type[] types = asm.GetTypes();

    foreach (var type in types)
    {
      if (type.IsSubclassOf(typeof(MonoBehavior)) || type.GetInterfaces().Contains(typeof(MonoBehavior)))
      {
        MethodInfo startMethod = type.GetMethod("Start", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { }, null);
        if (startMethod != null)
        {
          ConstructorInfo ctor = type.GetConstructor(new Type[] { });
          if (ctor != null)
          {
            object inst = ctor.Invoke(new object[] { });
            startMethod.Invoke(inst, new object[] { });
          }
        }
      }
    }
  }
}

interface MonoBehavior
{
}

class Example1 : MonoBehavior
{
  static void Start()
  {
    Console.WriteLine("Example1 Start");
  }
}

class Example2 : MonoBehavior
{
}

现在,如果你不喜欢创建一个对象,你可以使Start为静态,并且反射中的几行会像这样调整:

MethodInfo startMethod = type.GetMethod("Start", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { }, null);
if (startMethod != null)
{
  startMethod.Invoke(null, new object[] { });
}

请注意,我不再需要创建实例,并且传递给Invoke的第一个参数为null(这总是针对static方法完成)。

但是,我不会从阅读MonoBehaviour.Start上的Unity3D文档中得到印象,它打算以这种方式运行,更不用说静态了。我认为应该在其他各种条件下创建MonoBehaviour时运行。该模型不需要反射,但我建议构建一种工厂模型,在工厂对象的请求中创建MonoBeaviour对象 - 调用相应的AwakeStart返回实例之前的方法。

答案 1 :(得分:0)

类型不是它自己的子类,这就是为什么你有三种类型但只有2种匹配条件的原因。 (如果那是问题。)此外,MonoBehaviour没有Start()方法,或者我很累; - )。