有没有办法从其类型中获取 class 引用?
Is there a way to get a class reference from its type?
所以我正在开发游戏引擎,我正在尝试调用 classes 中使用的这些函数来继承父“行为”class。我试图通过使用 System.Reflection
获取所有子 classes 并使用该子 class 引用调用函数来实现这一点。但是,我这样做的方式要求我使用类型,并且为了调用这些函数,我需要引用 class。我正在尝试调用已在子 class 中覆盖的虚拟空隙,因此可能需要 class 的实例。
// Initializing variable "b" which is what stores all of the child classes
public static Type[] b = Assembly.GetAssembly(typeof(BaseBehavior)).GetTypes().Where(t => t.IsSubclassOf(typeof(BaseBehavior))).ToArray();
// Executing Start Function
for (int i = 0; i < b.Length; i++)
{
MethodInfo s = b[i].GetMethod("Start", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.IgnoreReturn, null, CallingConventions.HasThis, new Type[] { }, null);
if (s != null) Console.WriteLine(s.Name);
if (s != null && b[i] != null)
{
s.Invoke(b[i], null); // Requires an object reference, not a type
} else
{
Console.WriteLine("Invalid Method");
}
}
对于我正在做的事情,有什么我应该改变的吗,或者有什么我缺少的功能。我无法在其他任何地方找到答案,因此将不胜感激。
如果您不想实例化对象的实例,请将方法更改为 static
。当前,您正在显式传递 BindingFlags.Instance
,这意味着调用该方法将需要一个对象引用。如果它是静态的,那么您可以将 null
作为 Invoke()
方法的第一个参数传递,因为您不需要此类方法的对象引用。尝试:
MethodInfo s = b[i].GetMethod("Start", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.IgnoreReturn, null, CallingConventions.HasThis, new Type[] { }, null);
if (s != null)
{
Console.WriteLine(s.Name);
s.Invoke(null, null); // Pass null as the first parameter
} else
{
Console.WriteLine("Invalid Method");
}
如果需要调用实例方法,则需要先创建 b[i]
类型的实例,然后再将其传递给 Invoke()
:
var instance = Activator.CreateInstance(b[i]);
s.Invoke(instance, null);
这假设类型上有一个无参数的构造函数。如果没有这样的构造函数可用,那么您需要将必要的参数传递给 Activator.CreateInstance
。但是你需要比这个通用解决方案所建议的更多地了解类型......
我建议另一种方法。只需创建一个指向启动方法的委托,并使其从外部可见。然后您可以继续使用该委托调用 start 方法。它应该比使用反射快得多。
所以我正在开发游戏引擎,我正在尝试调用 classes 中使用的这些函数来继承父“行为”class。我试图通过使用 System.Reflection
获取所有子 classes 并使用该子 class 引用调用函数来实现这一点。但是,我这样做的方式要求我使用类型,并且为了调用这些函数,我需要引用 class。我正在尝试调用已在子 class 中覆盖的虚拟空隙,因此可能需要 class 的实例。
// Initializing variable "b" which is what stores all of the child classes
public static Type[] b = Assembly.GetAssembly(typeof(BaseBehavior)).GetTypes().Where(t => t.IsSubclassOf(typeof(BaseBehavior))).ToArray();
// Executing Start Function
for (int i = 0; i < b.Length; i++)
{
MethodInfo s = b[i].GetMethod("Start", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.IgnoreReturn, null, CallingConventions.HasThis, new Type[] { }, null);
if (s != null) Console.WriteLine(s.Name);
if (s != null && b[i] != null)
{
s.Invoke(b[i], null); // Requires an object reference, not a type
} else
{
Console.WriteLine("Invalid Method");
}
}
对于我正在做的事情,有什么我应该改变的吗,或者有什么我缺少的功能。我无法在其他任何地方找到答案,因此将不胜感激。
如果您不想实例化对象的实例,请将方法更改为 static
。当前,您正在显式传递 BindingFlags.Instance
,这意味着调用该方法将需要一个对象引用。如果它是静态的,那么您可以将 null
作为 Invoke()
方法的第一个参数传递,因为您不需要此类方法的对象引用。尝试:
MethodInfo s = b[i].GetMethod("Start", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.IgnoreReturn, null, CallingConventions.HasThis, new Type[] { }, null);
if (s != null)
{
Console.WriteLine(s.Name);
s.Invoke(null, null); // Pass null as the first parameter
} else
{
Console.WriteLine("Invalid Method");
}
如果需要调用实例方法,则需要先创建 b[i]
类型的实例,然后再将其传递给 Invoke()
:
var instance = Activator.CreateInstance(b[i]);
s.Invoke(instance, null);
这假设类型上有一个无参数的构造函数。如果没有这样的构造函数可用,那么您需要将必要的参数传递给 Activator.CreateInstance
。但是你需要比这个通用解决方案所建议的更多地了解类型......
我建议另一种方法。只需创建一个指向启动方法的委托,并使其从外部可见。然后您可以继续使用该委托调用 start 方法。它应该比使用反射快得多。