C# Lambda+Extensions+Fluent - 我该怎么做?

标签 c# lambda expression-trees fluent-interface

我希望能够创建采用给定对象的“转换”类,对其执行一系列转换(即更改属性值)并跟踪执行的转换。执行的转换将根据所提供对象的属性而有所不同。

我希望能够使用流畅风格的界面在给定的转换类中应用转换规则(有限且通用)。

在高层次上,我知道我可能会有一个 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/

相关文章:

c# - 为什么我不能在 for 循环中更改 linq IEnumerable 中的元素?

c# - Fxcop 自定义规则检查派生类名称以基类名称结尾

带有忽略大小写或 tolower 的 C# 表达式树

c# - 更新 SQL 语句未触发到数据库

c# - 如何使用 LINQ 使用 Azure AD 图形 API 客户端库 2.0 查找具有特定许可证的 Azure AD 用户

java - 根据另一个列表中的条件删除一个列表中的某些元素

linq - 将随机 Guid 列添加到 Linq to Entities 查询以获取随机记录

function - 在 Kotlin 中分配给变量的 Lambda 表达式。为什么?

c - 解析器树或表达式树

c# - 查询和映射复杂对象