代码之家  ›  专栏  ›  技术社区  ›  Edward Tanguay

Dictionary<string,object>是将未知变量集合传递给构造函数的最佳方法吗?

  •  2
  • Edward Tanguay  · 技术社区  · 15 年前

    一些 但不是所有的财产。

    我发现向每种对象传递参数的最佳方法是将它们全部打包在一个 Dictionary<string, object> 然后让基类SectionItem解包 常见的 具体的 一个。

    这工作得很好,但这完全是C#2,因为我只会在运行时捕获错误,而不会在编译期间捕获错误。有没有一种方法可以用泛型更优雅地实现这一点?

    alt text
    (来源: deviantsart.com )

    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;
            }
        }
    }
    
    2 回复  |  直到 6 年前
        1
  •  2
  •   Quartermeister    15 年前

    你能为每个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

        2
  •  0
  •   Richard    15 年前

    如果在编译时已知可能的名称集,并且使用C#4,则可以在构造函数上使用默认/可选参数。如果只有某些组合是有效的(例如,如果没有提供“Bar”和“Baz”,则只提供“Foo”),那么您仍然需要运行时检查。