使用反射来创建一个对象,需要使用“new”关键字。

3

我完全不了解反射,我试图从数据库记录中调用一个类名,然后加载该类并运行它,但我在哪里出错了,可能是我错过了一些非常愚蠢的东西。

例如,我将我的类放在不同的项目和脚本文件夹中,然后从数据库记录中调用其名称。

className = String.Format("Utilities.Scripts.{0}", script.ScriptClass);

然后在我的主程序中,我有以下代码:

// Get a type from the string 
Type type = Type.GetType(className);

// Create an instance of that type
Object obj = Activator.CreateInstance(type);

// Retrieve the method you are looking for
MethodInfo methodInfo = type.GetMethod("start");

// Invoke the method on the instance we created above
methodInfo.Invoke(obj, null);

但是在调试时,我发现我的细节已经传递到GetType(className)中,但是没有进入类型,因此也没有进入obj,这就是错误所在。


你能发布你的确切错误吗? - Colin D
System.ArgumentNullException - {"值不能为 null。\r\n参数名: type"} 谢谢 - Adamsk1
使用调试器逐步执行代码,并找出使用空参数调用的方法。然后,将它们改为非空。我的第一个猜测是将 methodInfo.Invoke() 的第二个参数改为空数组而不是 null。 - Colin D
2个回答

3
你需要提供类型的程序集限定名称(如此处所述),因为该类位于另一个项目中。此外,请确保您尝试从中加载类型的程序集与尝试加载它的程序集位于同一文件夹中,或者在GAC中。
对于以下定义的类:
namespace Foo.Bar
{
    public class Class1
    {

    }
}

完整的类名是 Foo.Bar.Class1。程序集限定名也指定了程序集的完整名称,例如 Foo.Bar.Class1, Foo.Bar, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35。您可以通过以下方式找到类型的程序集限定名:
Console.WriteLine(typeof(Foo.Bar.Class1).AssemblyQualifiedName)

不过,我是不是已经通过将项目、子文件夹和类名作为类型输入来实现了这一点?"Utilities.Scripts.{0}", script.ScriptClass"在调试时,这个显示得很好,但当你将鼠标悬停在类型上时,它什么也没有? 谢谢。 - Adamsk1
1
没有任何关系的是程序集限定名称和ProjectName.Folder.ClassName之间,这只是偶然的。我会编辑我的答案,以更清楚地定义程序集限定名称。 - James Curtis
太好了!解决了我的问题,并且在我更改数据库排序时加载了我的两个测试类。非常感谢您 :-) - Adamsk1

0

问题出在这一行:

Type type = Type.GetType(className);

由于此方法的特定重载在无法解析类型时不会引发异常。请改用此重载,它需要两个布尔值之一为throwOnError。将此参数设置为true,您将获得一个异常,应该帮助您调试为什么无法从传递的字符串中解析出类型。

我怀疑您需要一个类名和程序集名称。

Utilities.Scripts.SomeClass, SomeAssemblyName

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接