在 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.
我正在为使用一些非常复杂的 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.