2

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

2 回答 2

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

提供MyForm的是global和组件是一样的。如果表单在不同的程序集中,则首先使用Assembly.Loador加载它Assembly.LoadFrom,然后创建实例。

于 2013-01-24T15:05:09.437 回答
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;
        }
    }
}
于 2013-01-24T13:59:58.070 回答