Как вы можете создать экземпляр объекта со строкой и отправить параметр в C #? - PullRequest
2 голосов
/ 09 ноября 2009

Приведенный ниже код выдает этот вывод в порядке:

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 ]

8 голосов
/ 09 ноября 2009

Полагаю, вы можете использовать Activator.CreateInstance , который принимает параметры для ввода.

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

Или, как говорит Гру, просто брось:

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

        }
    }
}
3 голосов
/ 09 ноября 2009

Это успешно компилируется. Я только что попробовал.

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

делает код выполненным успешно.

Вы должны иметь в виду, что методы Reflection всегда возвращают null, когда они не могут найти что-то, а не вызывают исключение. Если ваш код ожидает, что Type.GetType всегда будет успешным, то вам нужно проверить наличие нулей и вызвать собственное исключение, в противном случае вы получите каскадные сбои, поскольку нулевые значения распространяются в остальной части кода.

1 голос
/ 09 ноября 2009

Могу ли я предложить Assembly.CreateInstance () Вы можете использовать эту функцию для создания экземпляра указанной сборки.

1 голос
/ 09 ноября 2009

Посмотрите на перегрузки для Activator.CreateInstance. Вы можете передать конструкторы в массиве объектов для одного из них.

...