2009-11-09 57 views
2

下面的代碼產生這樣的輸出罰款:如何使用字符串實例化對象並在C#中發送參數?

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

     } 
    } 
} 

回答

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

     } 
    } 
} 
+0

該代碼得到的錯誤是,期望BasePageItem和我們發送對象,我在我的例子中相應地改變它,但仍然無法獲得正確的語法。 –

+0

將其轉換爲BasePageItem。 – Groo

+0

我想發送「this」作爲正在實例化的類的*參數*,它繼承* BasePageItem,因爲BasePageItem在其構造函數中需要PageItemManager,而不是BasePageItem本身。 –

1

看看Activator.CreateInstance的重載。你可以傳入一個對象數組中的構造函數。

1

可能我su ggest Assembly.CreateInstance()您可以使用此函數來創建指定程序集的實例。

+0

通常你會使用'Activator.CreateInstance'而不是'Assembly。CreateInstance',但如果需要從特定程序集創建類型(例如,如果兩個程序集在同一個名稱空間中具有相同類型),則後者很有用。 –

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總是成功,那麼您需要檢查空值並提出自己的異常,否則當空值在代碼的其餘部分中傳播時,您會遇到級聯故障。

+0

有趣的是:你的解決方案編譯但給我一個運行時錯誤「值不能爲空」。它似乎想要在它爲空的時刻投射Activator.CreateInstance(...)。這會得到相同的錯誤:BasePageItem pageItem = Activator.CreateInstance(t,new object [] {this})as BasePageItem; –

相關問題