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

本文关键字:实例化 窗口 表单 运行时 数据库 | 更新日期: 2023-09-27 17:55:52

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

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

问题在于你的想法,即程序集名称是类名的一部分。诚然,您需要访问程序集,但最终类名只是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的设计。如果你真的想你的 Forms 没有命名空间,你只需要指定类名,排除程序集名称。只需致电:

CreateInstance<MyForm>("MyForm"); 

前提是MyForm global并且程序集相同。如果窗体位于不同的程序集中,则首先使用 Assembly.LoadAssembly.LoadFrom 加载它,然后创建实例。

您的密钥方法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;
        }
    }
}