Dean Martin
Dean Martin

Reputation: 1283

Instantiating windows form at runtime from database name C#

I am having trouble instantiating a form in c# whose name i retrieve from a database, i have eliminated namespaces completely just to be sure i am not getting the object name wrong but still every time the code runs, the object returns as null instead of being the appropriate form.

private static Object CreateObjectInstance(string strObjectName)
{
    Object obj = null; // Temporary object

    try
    {
        if (strObjectName.LastIndexOf(".") == -1) // If there is no '.' in the object name
            strObjectName = Assembly.GetEntryAssembly().GetName().Name + "." + strObjectName;

        obj = Assembly.GetEntryAssembly().CreateInstance(strObjectName);
    }
    catch (Exception ex)
    {
        clsAdmFunctions.RecordException(ex); // Record error to the database
        MessageBox.Show("Error instantiating the object\n\nDescription : "+ex.Message, "Object Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        obj = null;
    }

    return obj;
}

public static Form CreateForm(string strFormName)
{
    return (Form)CreateObjectInstance(strFormName);
}

Upvotes: 2

Views: 710

Answers (2)

nawfal
nawfal

Reputation: 73183

The problem is with your idea that assembly name is a part of your class name. True you need access to your assembly, but ultimately a class name is just Namespace.Class name. If you provide your actual namespace along with the class, then it works. Change your method to this, perhaps:

private static T CreateInstance<T>(string fullyQualifiedClassName)
{
    try
    {
        return (T)Activator.CreateInstance(Type.GetType(fullyQualifiedClassName));
    }
    catch (Exception ex)
    {
        clsAdmFunctions.RecordException(ex); // Record error to the database
        MessageBox.Show("Error instantiating the object\n\nDescription : " + ex.Message, "Object Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return default(T);
    }
}

In other words you need the namespace too if you're saving it in the database. Just save class.GetType() as such or class.GetType().ToString() after which you will see the namespace too saved. The reason is you can have classes with same name, namespace1.Person and namespace2.Person in the same assembly.

If you need to read all the namespaces in an assembly, you can do:

 foreach(var type in Assembly.WhateverAssembly().GetTypes())
     //print type.Namespace;

You're stuck if you dont know the exact namespace. May be you can assume it to be

var namespace = Assembly.WhateverAssembly().GetTypes()[0].Namespace;

You need to have namespaces for your classes, doing otherwise is against .NET's design. If you really really want to have no namespaces for your Forms, you just need to specify just the class name, exclude the assembly name. Just call:

CreateInstance<MyForm>("MyForm"); 

provided MyForm is global and the assembly is just the same. If forms are in different assembly, then load it first using Assembly.Load or Assembly.LoadFrom and then create instance.

Upvotes: 1

Belogix
Belogix

Reputation: 8147

Your key method CreateObjectInstance should work OK so I am guessing it is the parameter being passed in? In my example I've shown how to include full namespace and class name etc:

namespace Example.SubFolder
{
    internal class frmAdmAbout
    {
        public string Name { get; set; }
    }
}

namespace Example.ActualApp
{
    using System;
    using System.Reflection;

    internal class Program
    {
        static void Main(string[] args)
        {
            var newItem = CreateObjectInstance("Example.SubFolder.frmAdmAbout");
            if (newItem == null)
            {
                Console.WriteLine("Failed to create!");
            }
            else
            {
                Console.WriteLine("Successfully created!");
            }
            Console.ReadKey();
        }

        private static Object CreateObjectInstance(string strObjectName)
        {
            Object obj = null;

            try
            {
                if (strObjectName.LastIndexOf(".") == -1)
                    strObjectName = Assembly.GetEntryAssembly().GetName().Name + "." + strObjectName;

                obj = Assembly.GetEntryAssembly().CreateInstance(strObjectName);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error instantiating the object\n\nDescription : " + ex.Message);
                obj = null;
            }

            return obj;
        }
    }
}

Upvotes: 1

Related Questions