C# Reflection: Instantiate an object with string c

2020-02-25 23:13发布

问题:

my situation is the next: I'm working with Visual C# 2010 express developing a Windows Forms Application. When the user logins, dinamically build a menustrip with options loaded from a database table. In that table i save id, option name and Form Name.

So, suppose that in my project i have a Form named Contabilidad, it has Contabilidad.cs that is the main class , so if i wanna create a new form and show it i do this:

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

But in this case, because the menu options are stored in database, in database i only have the string "Contabilidad". So, i want to use C# reflection to create a instance of Contabilidad or any other form only with class name in string format.

First i tried this:

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

Because i read in a StackOverflow question that if i use null i'm referring to current assembly (my forms are all in the same project), but i get this message:

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

The class definition is the next:

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

Also i tried this:

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

But i get ArgumentNullException with this message:

Value cannot be null. Parameter name: type

Because t variable is null.

What i'm do wrong? Thanks in advance.

回答1:

Use the fully-qualified name of the type:

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

From the documentation for Assembly.GetType(string):

name Type: System.String The full name of the type. [...] The name parameter includes the namespace but not the assembly.



回答2:

You're trying to use the name of the class without specifying the namespace. This should be fine:

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

Every version of GetType requires the fully-qualified type name; the benefit of using Assembly.GetType is that at least you don't need to also include the assembly name, but as documented you still need the namespace:

The name parameter includes the namespace but not the assembly.

Note that to diagnose something similar in the future, it would have been worth looking at the value of t after the second line - it will be null, which is why the third line threw an exception.



回答3:

You should add the namespace:

assembly.GetType("AccountingSA.Contabilidad");


回答4:

Try this

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


回答5:

Try specifying your class this way:

ContabilidadNamespace.Contabilidad, ContabilidadAssembly


回答6:

Its too late in the thread to answer, but the earlier answer, in current .NET framework (4.7), not working (The line Assembly assembly = Assembly.Load("AccountingSA"); always throws FileIOException). Currently, working code is (Use Type directly)

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

or other way using Assembly is

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


标签: c# reflection