2

データベースから名前を取得したc#でフォームをインスタンス化するのに問題があります。オブジェクト名が間違っていないことを確認するために名前空間を完全に削除しましたが、コードが実行されるたびに、オブジェクトはnullではなく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

キーメソッドは正常に機能する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 に答える
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.Personその理由は、同じ名前のクラスをnamespace2.Person同じアセンブリに含めることができるためです。

アセンブリ内のすべての名前空間を読み取る必要がある場合は、次の操作を実行できます。

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

正確な名前空間がわからない場合は、行き詰まります。たぶんあなたはそれを仮定することができます

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

クラスに名前空間を設定する必要があります。そうしないと、.NETの設計に反します。フォームに名前空間を本当に持たせたくない場合は、クラス名だけを指定し、アセンブリ名を除外する必要があります。電話するだけです:

CreateInstance<MyForm>("MyForm"); 

提供されMyFormglobalおり、アセンブリはまったく同じです。フォームが別のアセンブリにある場合は、最初にAssembly.LoadまたはAssembly.LoadFromを使用してフォームをロードしてから、インスタンスを作成します。

于 2013-01-24T15:05:09.437 に答える