2010-06-26 69 views
2

我有一些「節項目」(課程,信息),從通用類型SectionItem繼承。各種類型的分部項目共享一些但不是全部屬性。Is Dictionary <string,object>將未知變量集合傳遞給構造函數的最佳方法是什麼?

我發現參數傳遞給每一個類的對象的最好的辦法就是收拾他們都在一個Dictionary<string, object>,然後讓基類SectionItem解壓共同的,每個繼承類解壓具體個。

這很好用,但是這都是C#2,因爲我只會在運行時捕獲錯誤,而不是在編譯期間捕獲錯誤。有沒有辦法更加優雅地使用泛型?

alt text http://www.deviantsart.com/upload/1hqkaoc.png

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

namespace TestPass234 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<SectionItem> sectionItems = new List<SectionItem>(); 

      { 
       Dictionary<string, object> vars = new Dictionary<string, object>(); 
       vars.Add("sectionNumber", 1); 
       vars.Add("title", "Lesson #1"); 
       vars.Add("startDate", new DateTime(2008, 12, 25)); 
       List<Flashcard> flascards = new List<Flashcard>(); 
       flascards.Add(new Flashcard { Question = "What color is the sky?", Answer = "blue" }); 
       flascards.Add(new Flashcard { Question = "What color is the sun?", Answer = "yellow" }); 
       vars.Add("flashcards", flascards); 
       SectionItem sectionItem = SectionItem.Instantiate("lesson", vars); 
       sectionItems.Add(sectionItem); 
      } 

      { 
       Dictionary<string, object> vars = new Dictionary<string, object>(); 
       vars.Add("title", "Info #1"); 
       vars.Add("content", "This is info number one."); 
       SectionItem sectionItem = SectionItem.Instantiate("info", vars); 
       sectionItems.Add(sectionItem); 
      } 

      foreach (var sectionItem in sectionItems) 
      { 
       Console.WriteLine(sectionItem.Render()); 
      } 
      Console.ReadLine(); 
     } 
    } 

    public class SectionItem 
    { 
     protected string _title; 

     public SectionItem() 
     { } 

     public SectionItem(Dictionary<string, object> vars) 
     { 
      _title = Convert.ToString(vars["title"]); 
     } 

     public static SectionItem Instantiate(string idCode, Dictionary<string, object> vars) 
     { 
      switch (idCode) 
      { 
       case "lesson": 
        return new SectionItemLesson(vars); 
       case "info": 
        return new SectionItemInfo(vars); 
       default: 
        return new SectionItem(); 
      } 
     } 

     public virtual string Render() 
     { 
      return "undefined section item"; 
     } 

    } 


    public class SectionItemLesson : SectionItem 
    { 
     private int _sectionNumber; 
     private DateTime _startDate; 
     private List<Flashcard> _flashcards = new List<Flashcard>(); 

     public SectionItemLesson(Dictionary<string, object> vars) : base(vars) 
     { 
      _sectionNumber = Convert.ToInt32(vars["sectionNumber"]); 
      _startDate = Convert.ToDateTime(vars["startDate"]); 
      _flashcards = vars["flashcards"] as List<Flashcard>; 
     } 

     public override string Render() 
     { 
      StringBuilder sb = new StringBuilder(); 
      sb.AppendLine(String.Format(">>> {0}. {1} (Starts {2:ddd, MMM d, yyyy})", _sectionNumber, _title, _startDate)); 
      foreach (var flashcard in _flashcards) 
       sb.AppendLine(" - " + flashcard.Render()); 
      return sb.ToString(); 
     } 
    } 

    public class SectionItemInfo : SectionItem 
    { 
     private string _content; 

     public SectionItemInfo(Dictionary<string, object> vars) 
      : base(vars) 
     { 
      _content = Convert.ToString(vars["content"]); 
     } 

     public override string Render() 
     { 
      StringBuilder sb = new StringBuilder(); 
      sb.AppendLine(String.Format(">>> {0}", _title)); 
      sb.AppendLine(String.Format(" {0}", _content)); 
      return sb.ToString(); 
     } 
    } 

    public class Flashcard 
    { 
     public string Question { get; set; } 
     public string Answer { get; set; } 

     public string Render() 
     { 
      return "Q: " + Question + " A: " + Answer; 
     } 
    } 
} 
+0

你可能會考慮使用匿名類和反射 - 但這在編譯時不會幫助你。所有字段都是動態的,還是可以將字段添加到SectionItem? – simendsjo 2010-06-26 10:41:07

+0

我將添加多種分段項目,例如SectionItemNote,SectionItemEvent等,所以常見和特定的字段都將被添加,但從不動態。我只是想,可能有一些方法來創建一個「多個通用」。我想最好的是創建一個SectionItemParameters類,它具有所有可能的參數,因此我可以在構造函數中將它們複製掉,而不會發生混亂的轉換。 – 2010-06-26 10:46:13

回答

2

你能爲每個SectionItem類創建一個'parameters'類嗎?

public class SectionItemParameters 
{ 
    public string Title { get; set; } 
} 

public class SectionItemLessonParameters 
    : SectionItemParameters 
{ 
    public int SectionNumber { get; set; } 
    public DateTime StartDate { get; set; } 
    public List<Flashcard> Flashcards { get; set; } 
} 

public class SectionItemInfoParameters 
    : SectionItemParameters 
{ 
    public string Content { get; set; } 
} 

然後,層次結構中的每個類都可以在強類型對象中接收其參數。您的工廠方法Instantiate將採用SectionItemParameters並轉換爲正在調用的構造函數的適當類型。

+0

謝謝,這就是我所做的,使得更有意義,但我用一個結構來節省開銷,只使用一個類而不是繼承參數類,從而保持這些微小幫助類的數量:http:// tanguay.info/web/index.php?pg=codeExamples&id=381 – 2010-06-26 12:31:53

0

如果這組可能的名字是在編譯時使用C#4,你可以在構造函數中使用缺省的/可選參數聞名。如果只有某些組合是有效的(例如,如果既沒有提供「Bar」又沒有提供「Baz」,那麼只提供「Foo」),那麼你仍然需要運行時檢查。

但是,如果這組名稱是真正動態的,那麼只有字典或匿名類型的選項(並使用反射來提取正文中的一組名稱)。

相關問題