C# 反射:使用字符串类名实例化对象

9

我的情况是这样的:我正在使用Visual C# 2010 express开发Windows Forms应用程序。当用户登录时,从数据库表中动态构建一个菜单栏。在该表中,我保存id、选项名称和窗体名称。

因此,假设在我的项目中我有一个名为“会计”的表单,它具有Contabilidad.cs作为主类,因此如果我想创建一个新表单并显示它,我会这样做:

Contabilidad frmConta = new Contabilidad();
frmConta.Show();

但在这种情况下,由于菜单选项存储在数据库中,我只有字符串"Contabilidad"。因此,我希望使用C#反射来创建一个Contabilidad实例或任何其他形式的实例,只需使用类名的字符串格式。
首先,我尝试了以下方法:
Form frmConta= (Form)Activator.CreateInstance(null, "Contabilidad").Unwrap();

因为我在StackOverflow的一个问题中看到,如果我使用null,我就是在引用当前程序集(我的窗体都在同一个项目中),但是我收到了这个消息:

Could not load type 'Contabilidad' from assembly 'AccountingSA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

类定义如下:

namespace AccountingSA {
public partial class Contabilidad : Form
{
    public Contabilidad()
    {
        InitializeComponent();
    } ...

我也尝试过这个:

Assembly assembly = Assembly.Load("AccountingSA");
Type t = assembly.GetType("Contabilidad");
Form frmConta = (Form)Activator.CreateInstance(t);

但是我使用此代码时遇到了ArgumentNullException异常,异常信息如下:
Value cannot be null. Parameter name: type

因为 t 变量为空。
我做错了什么?谢谢。
6个回答

15

使用类型的完全合格名称:

Type t = assembly.GetType("AccountingSA.Contabilidad");

根据Assembly.GetType(string)的文档:

name类型: System.String 类型的完整名称。 [...] 名称参数包含命名空间,但不包括程序集。


14

您正在尝试使用类名而没有指定命名空间。这样应该是可以的:

Assembly assembly = Assembly.Load("AccountingSA");
Type t = assembly.GetType("AccountingSA.Contabilidad");
Form frmConta = (Form)Activator.CreateInstance(t);

每个版本的GetType都需要完全限定的类型名称;使用Assembly.GetType的好处是,至少您不需要包括程序集名称,但是,正如文档所述,您仍然需要命名空间:

名称参数包括命名空间但不包括程序集。

请注意,为了在将来诊断类似的问题,值得在第二行代码后查看t的值-它将为null,这就是为什么第三行代码会引发异常的原因。

1

你应该添加命名空间:

assembly.GetType("AccountingSA.Contabilidad");

1

试试这个

Form frmConta= (Form)Activator.CreateInstance(null, "AccountingSA.Contabilidad").Unwrap();

0

虽然已经太迟了,不过之前的回答在当前 .NET framework(4.7)中已经不起作用了(此行代码:Assembly assembly = Assembly.Load("AccountingSA"); 总是会抛出 FileIOException 异常)。现在有效的代码是(直接使用 Type)

Type t = Type.GetType("AccountingSA.Contabilidad");
Form frmConta = (Form)Activator.CreateInstance(t);

或者使用汇编语言的方式是:

Assembly assembly = typeof(Form).Assembly;
Type t = assembly.GetType("AccountingSA.Contabilidad");
Form frmConta = (Form)Activator.CreateInstance(t);

0

尝试以这种方式指定您的类:

ContabilidadNamespace.Contabilidad, ContabilidadAssembly

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