65.9K
CodeProject 正在变化。 阅读更多。
Home

C# 中的 Fluent 接口和方法链

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (20投票s)

2013年8月21日

CPOL

4分钟阅读

viewsIcon

122245

人类是懒惰的,程序员也是人类 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 语言,并且该语言映射到流畅的接口语句。    

进一步阅读,请观看下面的面试准备视频和分步视频系列。

© . All rights reserved.