我希望能够创建采用给定对象的“转换”类,对其执行一系列转换(即更改属性值)并跟踪执行的转换。执行的转换将根据所提供对象的属性而有所不同。
我希望能够使用流畅风格的界面在给定的转换类中应用转换规则(有限且通用)。
在高层次上,我知道我可能会有一个 ITransformer、一个 ITransformationRule 和 ITransformationResult,以及一些其他对象来实现这一点。
创建转换类时我希望代码如何工作...
public OfflinePersonToOnlineTransformation : TransformerBase<Person>
{
public OfflinePersonToOnlineTransformation()
{
Transform(x => x.PersonClassification)
.WhenCreatedBefore("1/1/2000")
.ClassifyAs("Online");
}
}
我知道我的 TransformerBase 需要实现采用 Func 或 Expression 的“Transform”方法,并且我知道它需要保留 ITransformationRules 的集合。我也明白我可能会为“WhenCreatedBefore”和“ClassifyAs”方法使用扩展方法。
问题是,我想不出如何让它全部工作。我已经查看了 Fluent Validation .NET 的源代码,因为它以这种方式进行验证,但复杂性让我感到沮丧。我正在寻找涵盖此内容的教程,或者有人以非常简单的方式将其拼写出来。
提前致谢。
最佳答案
当 linq 为您完成大部分工作时,您不太清楚为什么要付出所有这些努力:
IEnumerable<Person> somePeople; // from wherever
somePeople.Where(x => x.CreateDate < new DateTime(2000,1,1))
.ForEach(x => x.PersonClassification = "Online");
只需从 here 添加 ForEach注意为什么默认情况下不包含它的原因。
如果你想让 WhereCreatedBefore 更好,那么一个简单的扩展如下:
static class PersonExtensions
{
public static bool WhereCreatedBefore(this Person p,
int year, int month, int day)
{
return p.CreateDate < new DateTime(year,month,day);
}
}
它本身很有用,并为您提供:
somePeople.Where(x => x.CreatedBefore(2000,1,1))
.ForEach(x => x.PersonClassification = "Online");
当简单地扩展 linq 提供的工具让事情变得更容易时,为什么要限制自己。
如果您想链接多个副作用,只需对 ForEach 进行简单更改,如下所示:
public static IEnumerable<T> Modify<T>(
this IEnumerable<T> input, Action<T> action)
{
foreach (var x in input)
{
action(x);
yield return x;
}
}
给你:
somePeople.Where(x => x.CreatedBefore(2000,1,1))
.Modify(x => x.PersonClassification = "Online");
.Modify(x => x.LastModifiedBy = Environment.UserName);
或者如果你使用语言集成的一部分:
(from p in somePeople where p.CreatedBefore(2000,1,1)) select p)
.Modify(p => p.PersonClassification = "Online");
.Modify(p => p.LastModifiedBy = Environment.UserName);
如果您真的*想要,您可以像这样编写一个 ClassifyAs 扩展:
public static IEnumerable<Person> ClassifyAs(
this IEnumerable<Person> input, string classification)
{
foreach (var p in input)
{
p. PersonClassification = classification;
yield return p;
}
}
给你你的原件:
(from p in input where p.CreatedBefore(2000,1,1)) select p).ClassifyAs("Online");
这是一个类轮!不需要花哨的框架或类型层次结构,只需要一些有用的扩展方法。 Linq 通常设计良好、实现良好、无处不在并且很好地集成到 c# 中。重新实现它的查询部分是愚蠢和浪费的,你想要的是添加副作用导致操作。这很好(你有可变对象,所以这几乎不会引起问题)只需添加这些操作。让他们继续产生他们的输入将使您的代码风格流畅。
关于C# Lambda+Extensions+Fluent - 我该怎么做?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1315483/