C# 中的 Fluent 接口和方法链






4.93/5 (20投票s)
人类是懒惰的,程序员也是人类 J。我们喜欢简单和干净的东西。所以如果你看到编程的演变,我们最初是从函数式编程开始的,然后演变成面向对象编程。就像函数式程序员一样,我们过去常常记住方法 a
人类是懒惰的,程序员也是人类 J。我们喜欢简单和干净的东西。所以如果你看到编程的演变,我们最初是从函数式编程开始的,然后演变成面向对象编程
因此,作为函数式程序员,我们过去常常记住“Add”、“Subtract”、“Multiply”和“Divide”等方法和函数名称,在 OOP 中,我们只需要记住类“Maths”,并且当我们创建该类的对象时,所有函数都会弹出。
但是,作为面向对象程序员,我们需要记住 OOP 中有两个世界,一个创建类,另一个通过创建对象来使用它。
因此,通过遵循良好的 OOP 原则,如抽象、封装等,开发人员编写了下面的“Customer”类,这样使用该类的其他开发人员就不会觉得它很复杂。
public class Customer { private string _FullName; public string FullName { get { return _FullName; } set { _FullName = value; } } private DateTime _Dob; public DateTime Dob { get { return _Dob; } set { _Dob = value; } } private string _Address; public string Address { get { return _Address; } set { _Address = value; } } }
现在,想要使用我们的“Customer”类的消费者将创建客户对象,设置属性并调用方法。以下是相同的示例代码。
Customer customer = new Customer(); customer.FullName = "Shiv"; customer.Dob = Convert.ToDateTime("1/1/2008"); customer.Address = "Mumbai";
现在让我们放大上面的消费者代码。它复杂吗?如果你是 C# 开发人员或面向对象的程序员,可能不会。
但是,如果您的消费者是测试人员,他们真的了解 C#,并且希望拥有更简单的接口来调用您的客户类以进行单元测试呢?
如果您是组件销售商,并且希望通过简化的界面给您的组件消费者带来惊喜。您希望与您的竞争对手有所不同。
欢迎来到“流畅接口”的概念。
“流畅接口通过使您的代码更简单、更易读和可发现来简化您的对象使用代码。”
因此,如果我们的组件消费者可以用简单的英语句子编写对象调用代码,如下所示,那就“太棒了”,对吧。
customer.NameOfCustomer("Shiv") .Bornon("12/3/1075") .StaysAt("Mumbai");
所以现在下一件事是如何实现“流畅”接口。这是通过使用“方法链”完成的。
“方法链”是一种常见技术,其中每个方法返回一个对象,并且所有这些方法可以链接在一起形成单个语句。
因此,我们可以将上面的客户类包装在另一个类(“CustomerFluent”)中,该类将实现方法链并以简化的格式公开链式方法。
因此,您可以在下面的代码中看到方法“NameofCustomer”、“BornOn”接受输入并返回“CustomerFluent”类。
public class CustomerFluent { private Customer obj = new Customer(); public CustomerFluent NameOfCustomer(string Name) { obj.FullName = Name; return this; } public CustomerFluent Bornon(string Dob) { obj.Dob = Convert.ToDateTime(Dob); return this; } public void StaysAt(string Address) { obj.Address = Address; } }
现在您的客户端代码简单、简洁而且流畅,如下面的代码所示。
customer.NameOfCustomer("Shiv") .Bornon("12/3/1075") .StaysAt("Mumbai");
我看到了流畅接口的四个明显用途:-
LINQ 查询
var x = context.Users.Select(u => new { u.Id, u.Name });
单元测试
Assert.AreEqual(obj.Expected,obj1.Actual);
模拟测试
Container.GetMock() .Setup(s => s.Save(new Person())) .Returns(true) .Verifiable();
DSL(特定领域语言)
DSL 是一种供不理解编程的简单用户使用的语言。所以他们可以用简单的英语输入一些内容,如下所示。这将进行解析并检查语法。稍后,这个句子可以映射到一个内部的流畅接口语句。
task "warn if website is not alive": every 1.Hour starting now when WebSite("http://www.questpond.com ").IsAlive is false then:notify "admin@example.org", "site down!"
以下是上述 DSL 可以映射到的流畅接口语句的代码。
new FluentTask("alert if site is down") .Every( TimeSpan.FromMinutes(3) ) .StartingFrom( DateTime.Now ) .When(delegate { return WebSite("http://www.questpond.com").IsAlive == false; }) .Execute(delegate { Notify(“admin@example.org”, “site down!”); });
流畅接口总是好的吗?
如果您正在为开发人员创建流畅的接口,那么您可能是在浪费时间。开发人员在使用 new 关键字创建对象和设置属性方面是一致的。即使您为他们创建了一些简单的东西,他们也坚持使用某种使用方法,您会发现您添加的复杂性比简化它更多。
我们需要理解的第二件事是,我们需要编写更多的代码来创建流畅接口。正如您在之前的代码中看到的那样,我创建了一个单独的类来简化接口。
您需要流畅接口的情况很少,以下是其中的一些:-
- 在单元测试期间,当开发人员不是成熟的程序员时。
- 您希望您的代码可供非程序员阅读,以便他们可以理解代码是否满足他们的领域逻辑。
- 您是组件销售商,并且希望通过简化您的界面在市场上脱颖而出,与其他人相比。
- 您正在创建一种 DSL 语言,并且该语言映射到流畅的接口语句。
进一步阅读,请观看下面的面试准备视频和分步视频系列。