【问题标题】:Is a generic object builder possible in C#?在 C# 中是否可以使用通用对象生成器?
【发布时间】:2015-02-25 22:20:56
【问题描述】:

我正在为使用一些相当复杂的 DTO 组合的报告系统编写一些单元测试。为了测试系统,我发现自己写了很多这样的代码:

var items = new List<Item>
{
    new Item
    {
        Things =
            new List<Thing>
            {
                new Thing
                {
                    Stuff =
                        new Stuff
                        {
                            Widgets = new List<Widget> {new Widget {Color = "Red"}}
                        },
                    Bobbles = new List<Bobble>{new Bobble(), new Bobble()}
                }
            }
    }
};

这让我觉得冗长而繁琐,所以我的第一个想法是使用具有流畅界面的构建器模式:

var items = ItemBuilder.AddItem()
                           .WithThing()
                           .WithStuff()
                           .WithWidget()
                           .WithColor("Red");

或者类似的东西。然后我突然想到我需要像这样创建其他对象,如果我可以使用泛型将其应用于我需要的任何对象,那就太好了:

var items = Builder.Add<Item>()
                           .With<Thing>()
                           .With<Stuff>()
                           .With<Widget>()
                           .With<Color>("Red");

显然,这些示例只是近似真实界面的样子。

使用诸如泛型、lambda 和表达式树之类的语法糖,C# 是否可以做到这一点?

我搜索了是否有人尝试过这样的事情,但只找到了一两个关于该主题的不完整系列博客文章。在我看来,如果可能的话,将会有一个完整的示例或一个开源或商业库可用。

【问题讨论】:

  • 我不明白为什么它不可能。
  • @MarcinJuraszek:请给出答案,以便我们投票。 :-) ...除了开玩笑,你对这个问题有什么期待?是的,这似乎是可能的。您是否希望有人为它脱口而出整个代码?这是相当多的工作。
  • 当然不是。我没有要求任何人“给我密码”。我希望得到确认(你已经给出了),我不会浪费我的时间来尝试这个,并且可能是一个链接到某人已经开创了这个想法的文章或图书馆。

标签: c# generics expression-trees builder


【解决方案1】:

我不明白为什么这是不可能的。您可能需要一些不同的语法来使结构更明显,例如:

Builder.Add<Item>(i =>
           i.With<Thing>(t =>
               t.With<Stuff>(s =>
                   s.Add<Widget>(w => w.With<string>("Red"))
                    .Add<Widget>(w => w.With<string>("Green")))
                .Add<Bubble>()
                .Add<Bubble>()));

它假定给定类型只有一个属性。例如。 With&lt;T&gt; 将查找类型为 &lt;T&gt; 的属性,Add&lt;T&gt; 将查找类型为 List&lt;T&gt; 的属性。

当有多个给定类型的属性时,它会变得有点混乱。您必须以某种方式确定应该使用给定值设置哪一个。

s.Add<Widget>(w => w.With(x => x.Color, "Red").With(x => x.Name, "MyWidget"));

真的快变丑了。性能也不理想,所以除了为单元测试制作实例之外,我看不到任何实际用途。

我对这样的现有库一无所知。

【讨论】:

    【解决方案2】:

    听起来像 NBuilder 可以满足您的要求:https://code.google.com/p/nbuilder/

    它已经存在,被广泛使用并且非常流行。

    【讨论】:

      【解决方案3】:

      如果 XML、JSON 和 XAML 教会了我们什么,那就是 声明性语言比命令性语言更适合创建对象图

      忘记所有这些,使用 XML、JSON 或 XAML 反序列化:

      这是一个使用 JSON 的代码示例:

      "items": [
          "item": { 
             "Things": [
                 "Thing": {
                     "Stuff": {
                         "Widgets" [
                            "Widget": {"Color" = "Red"}
                          ],
                      "Bobbles": [ 
                         "Bobble": { }],
                     },
                  },
              ],
           },
       },
      

      然后,只需使用许多知名的反序列化库(例如Json.NET),即可将序列化数据转换为强类型对象图。

      免责声明:我手动输入了上面的 JSON,所以它可能有语法错误,但你明白了。

      【讨论】:

      • 除了 C# 对象初始化语法声明性(子)语言。
      猜你喜欢
      • 2018-09-30
      • 1970-01-01
      • 2019-04-22
      • 2016-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-08
      • 1970-01-01
      相关资源
      最近更新 更多