2

以下のコードは、この出力を正常に生成します。

This is page one.
This is page two.

しかし、PageItemオブジェクトが?から動的にインスタンス化されるように変更するにはどうすればよいList<string>ですか?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestInstant
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> pageItemsIdCodes = new List<string>() { "PageItem1", "PageItem2" };
            PageItemManager pageItemManager = new PageItemManager(pageItemsIdCodes);
            pageItemManager.DisplayMenu();

            Console.ReadLine();
        }
    }

    class PageItemManager
    {
        private Dictionary<string, BasePageItem> PageItemRecords = new Dictionary<string, BasePageItem>();
        public PageItemManager(List<string> pageItemsIdCodes)
        {
            //manually
            PageItemRecords.Add("PageItem1", new PageItem1(this));
            PageItemRecords.Add("PageItem2", new PageItem2(this));

            //HOW DO i DO THIS DYNAMICALLY:
            //PSEUDO-CODE:
            //foreach (string pageItemIdCode in pageItemsIdCodes)
            //{
            //    Type t = Type.GetType(pageItemIdCode);
            //    //ERROR: Cannot implicitly convert type 'TestInstant.PageItemManager' to 'TestInstant.BasePageItem'
            //    BasePageItem pageItem = Activator.CreateInstance(t, new BasePageItem[] { this });
            //    PageItemRecords.Add(pageItemIdCode, pageItem);
            //}

                    //Type t = Type.GetType(pageItemIdCode);
                    //ERROR: Cannot implicitly convert type 'object' to 'TestInstant.BasePageItem'.
                    //BasePageItem pageItem = Activator.CreateInstance(t); // Change constructor
                    //pageItem.PageItemManager = this; // Add SetMananger call to BasePageItem
                    //PageItemRecords.Add(pageItemIdCode, pageItem);

        }

        public void DisplayMenu()
        {
            foreach (var pageItemRecord in PageItemRecords)
            {
                Console.WriteLine(pageItemRecord.Value.Title);
            }
        }
    }

    class BasePageItem
    {
        public string Title { get; set; }
        protected PageItemManager pageItemManager;
        public BasePageItem(PageItemManager pageItemManager)
        {
            this.pageItemManager = pageItemManager;
        }
    }

    class PageItem1 : BasePageItem
    {
        public PageItem1(PageItemManager pageItemManager)
            : base(pageItemManager)
        {
            Title = "This is page one.";
        }
    }

    class PageItem2 : BasePageItem
    {
        public PageItem2(PageItemManager pageItemManager)
            : base(pageItemManager)
        {
            Title = "This is page two.";

        }
    }
}
4

4 に答える 4

8

入力用のパラメーターを受け取るActivator.CreateInstanceを使用できると思います。

foreach (string pageItemIdCode in pageItemsIdCodes)
{
   Type t = Type.GetTypeFromProgID(pageItemIdCode);
   Object pageItem = Activator.CreateInstance(t, new object[]{this});
   PageItemRecords.Add(pageItemIdCode, pageItem);
}

または groo が言うように、キャストするだけです:

foreach (string pageItemIdCode in pageItemsIdCodes)
{
   Type t = Type.GetTypeFromProgID(pageItemIdCode);
   BasePageItem pageItem = (BasePageItem)Activator.CreateInstance(t, new object[]{this});
   PageItemRecords.Add(pageItemIdCode, pageItem);
}

実際の型を返したい場合は、次のようにすることもできます。

foreach (string pageItemIdCode in pageItemsIdCodes)
{
   Type t = Type.GetTypeFromProgID(pageItemIdCode);
   BasePageItem pageItem = Activator.CreateInstance(t); // Change constructor
   pageItem.SetMananger(this); // Add SetMananger call to BasePageItem
   PageItemRecords.Add(pageItemIdCode, pageItem);
}

完全な動作例は次のとおりです。

using System;
using System.Collections.Generic;
using System.Text;

namespace TestInstant
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> pageItemsIdCodes = new List<string>();
            pageItemsIdCodes.Add("PageItem1");
            pageItemsIdCodes.Add("PageItem2");
            PageItemManager pageItemManager = new PageItemManager(pageItemsIdCodes);
            pageItemManager.DisplayMenu();

            Console.ReadLine();
        }
    }

    class PageItemManager
    {
        private Dictionary<string, BasePageItem> PageItemRecords = new Dictionary<string, BasePageItem>();
        public PageItemManager(List<string> pageItemsIdCodes)
        {
            //manually
            //PageItemRecords.Add("PageItem1", new PageItem1(this));
            //PageItemRecords.Add("PageItem2", new PageItem2(this));

            foreach (string pageItemIdCode in pageItemsIdCodes)
            {
                Type t = Type.GetType("TestInstant."+pageItemIdCode);
                BasePageItem pageItem = (BasePageItem)Activator.CreateInstance(t, new Object[] { this });
                PageItemRecords.Add(pageItemIdCode, pageItem);
            }

        }

        public void DisplayMenu()
        {
            foreach (BasePageItem pageItemRecord in PageItemRecords.Values)
            {
                Console.WriteLine(pageItemRecord.Title);
            }
        }
    }

    class BasePageItem
    {
        private string mTitle;
        public string Title { get { return mTitle; } set { mTitle = value; } }
        protected PageItemManager pageItemManager;
        public BasePageItem(PageItemManager pageItemManager)
        {
            this.pageItemManager = pageItemManager;
        }
    }

    class PageItem1 : BasePageItem
    {
        public PageItem1(PageItemManager pageItemManager)
            : base(pageItemManager)
        {
            Title = "This is page one.";
        }
    }

    class PageItem2 : BasePageItem
    {
        public PageItem2(PageItemManager pageItemManager)
            : base(pageItemManager)
        {
            Title = "This is page two.";

        }
    }
}
于 2009-11-09T16:50:32.123 に答える
3

これは正常にコンパイルされます。試してみました。

foreach(string pageItemIdCode in pageItemsIdCodes) {
    Type t = Type.GetType(pageItemIdCode);
    BasePageItem pageItem = (BasePageItem) Activator.CreateInstance(t, new object[] { this });
    PageItemRecords.Add(pageItemIdCode, pageItem);
}

pageItemIdCode値が正しくないため、実行時に失敗します。次のように変更します。

List<string> pageItemsIdCodes = new List<string>() { "TestInstant.PageItem1", "TestInstant.PageItem2" };

コードを正常に実行します。

nullリフレクション メソッドは、何かが見つからない場合、例外を発生させるのではなく、常に戻ることに注意する必要があります。コードが常に成功することを期待Type.GetTypeしている場合は、null をチェックして独自の例外を発生させる必要があります。そうしないと、null がコードの残りの部分に伝播されるため、カスケード エラーが発生します。

于 2009-11-09T16:54:23.713 に答える
1

Assembly.CreateInstance() この関数を使用して、指定したアセンブリのインスタンスを作成できます。

于 2009-11-09T16:51:01.343 に答える
1

Activator.CreateInstance のオーバーロードを見てください。オブジェクト配列でコンストラクターを渡すことができます。

于 2009-11-09T16:49:00.053 に答える