在 C# 中是否可以使用通用对象生成器?

Is a generic object builder possible in C#?

我正在为使用一些非常复杂的 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# 中是否可行?

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

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

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<T> 将查找类型为 <T> 的 属性,而 Add<T> 将查找类型为 List<T>.

的 属性

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

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

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

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

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

它已经存在,被广泛使用并且非常受欢迎。

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

忘记所有这些并使用 XML、JSON 或 XAML de/serialization:

这是您的代码的示例,使用 JSON:

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

然后,只需使用许多著名的 de/serialization 库(例如 Json.NET)中的任何一个,即可将序列化数据转换为强类型对象图。

Disclaimer: I hand-typed the above JSON so it might have syntax errors, but you get the idea.