繁体   English   中英

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

[英]How can I invoke a method from a Type or its derived Types?

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

关于MonoBehavior.Start更多信息可以在这里阅读。

我想在从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
{
}

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

我将为您提供代码,使您可以调用程序集中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方法。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM