在运行时从数据库名称C#实例化窗体

时间:2013-01-24 13:42:33

标签: c#

我无法在c#中实例化一个名称我从数据库中检索的表单,我完全删除了名称空间只是为了确保我没有得到对象名称错误但仍然每次代码运行时,对象都返回null而不是适当的形式。

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);
}

2 个答案:

答案 0 :(得分:1)

您的密钥方法CreateObjectInstance应该正常工作,所以我猜它是传入的参数?在我的例子中,我展示了如何包含完整的命名空间和类名等:

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;
        }
    }
}

答案 1 :(得分:1)

问题在于你的想法是程序集名称是你的类名的一部分。确实,您需要访问您的程序集,但最终类名称只是Namespace.Class名称。如果您提供实际的命名空间以及类,那么它可以工作。将您的方法改为此,或许:

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);
    }
}

换句话说,如果要将其保存在数据库中,则还需要命名空间。只需保存class.GetType()class.GetType().ToString(),之后您就会看到名称空间太保存了。原因是您可以在同一个程序集中使用同名的namespace1.Personnamespace2.Person类。

如果需要读取程序集中的所有名称空间,可以执行以下操作:

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

如果你不知道确切的命名空间,你就会陷入困境。也许你可以假设

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

您需要为您的类创建名称空间,否则将违反.NET的设计。如果你真的想要没有表单的命名空间,你只需要指定类名,排除程序集名称。请致电:

CreateInstance<MyForm>("MyForm"); 

提供MyFormglobal且程序集完全相同。如果表单位于不同的程序集中,请先使用Assembly.LoadAssembly.LoadFrom加载它,然后创建实例。