Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Reflection: Instantiate an object with string class name

Tags:

c#

reflection

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.

like image 355
Oscar Calderon Avatar asked Aug 13 '11 18:08

Oscar Calderon


3 Answers

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.

like image 159
Ani Avatar answered Nov 01 '22 20:11

Ani


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.

like image 20
Jon Skeet Avatar answered Nov 01 '22 22:11

Jon Skeet


You should add the namespace:

assembly.GetType("AccountingSA.Contabilidad");
like image 1
Yousef Avatar answered Nov 01 '22 22:11

Yousef