博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用界面创建.scr 文件_为您的.Net类创建一个流畅的界面
阅读量:2531 次
发布时间:2019-05-11

本文共 10739 字,大约阅读时间需要 35 分钟。

用界面创建.scr 文件

I have seen a presentation lately about unit testing. One of the aspect covered by the presentation was the use of

我最近看过有关单元测试的演示。 演讲涉及的方面之一是使用

fluent interface to ease the wording of the tests (and ease the reading at the same time).

Is that limited to unit testing? Of course not. What a great way to provide an API to many of our classes.

这仅限于单元测试吗? 当然不是。 为我们的许多类提供API的好方法。

This article will show you how to create fluent interface in your own classes to use from anywhere you are using your classes.

本文将向您展示如何在自己的班级中创建流畅的界面,以便在您使用班级的任何地方使用。

这是什么 (What it is)

Consider this first example:

考虑第一个示例:

Dim s As String = "Eric Moreau"s = s.Trim()s = s.ToUpper()s = s.Replace("R", "z")

The readability of these statements is arguable at best and it is not very efficient (knowing that strings are immutable). It is also a bit too long to write. We don’t want to always break line and assign again.

这些语句的可读性充其量是有争议的,并且效率不是很高(知道字符串是不可变的)。 写的时间也太长了。 我们不想总是换行并重新分配。

Another way of writing the same as above, is this simple line:

与上面相同的另一种编写方式是以下简单的代码行:

Dim s As String = "Eric Moreau".Trim().ToUpper().Replace("R", "z")

This is an example of a fluent interface that you have surely used for years. The result of the first string is passed to the Trim method which is in turn passed to the ToUpper method to finally be passed to the Replace method before being returned to the variable.

这是您已经使用多年的流利界面的示例。 第一个字符串的结果传递给Trim方法,该方法又传递给ToUpper方法,最后传递给Replace方法,然后返回变量。

If you have used LINQ, Entity Framework, NHibernate, most mocking tools, and many others, you have already used fluent interfaces maybe without explicitly knowing you were using them.

如果您使用过LINQ,实体框架,NHibernate,大多数模拟工具以及许多其他工具,那么您可能已经使用过流畅的接口,而可能没有明确地知道自己正在使用它们。

Fluent interface is normally implemented by using method cascading to relay the instruction context of a subsequent call (). A different way of explaining it is that it is a sequence of methods that can be chained one after the other.

流利的接口通常通过使用级联的方法来中继后续调用的指令上下文来实现( )。 解释它的另一种方式是,它是一系列可以彼此连锁的方法。

Here is an example of a LINQ query that uses fluent interface (exposed by extension methods in this case):

这是一个使用流畅接口的LINQ查询示例(在这种情况下,扩展方法公开了该查询):

Dim dir As New IO.DirectoryInfo("C:\Windows\System32")Dim fileList = dir.GetFiles("*.*").    Where(Function(f) f.Name.StartsWith("odbc")).    OrderBy(Function(f) f.FullName)

The Where and the OrderBy methods chains on the result of the GetFiles method and it reads very fluently (even if I prefer the lambda format of C# over the one of VB but that’s another story).

Where和OrderBy方法链接到GetFiles方法的结果,并且读取非常流畅(即使我更喜欢C#的Lambda格式而不是VB格式,但这是另一回事了)。

可下载的演示应用程序 (Downloadable demo application)

The downloadable demo solution of this month contains both VB and C#.

本月可下载的演示解决方案包含VB和C#。

Figure 1: The demo application in action

图1:正在运行的演示应用程序

The fluent interface demo application

备择方案 (Alternatives)

Through the years, developers asked Microsoft to help them save a few keystrokes and make their code more readable. Here is a sample of what we are trying to improve here:

多年来,开发人员要求Microsoft帮助他们节省一些击键并使其代码更易读。 以下是我们在此处尝试改进的示例:

Dim emp As Employee = New Employeeemp.Name = "Eric Moreau"emp.Dob = New DateTime(1970, 5, 28)emp.HireDate = New DateTime(2007, 2, 1)emp.Salary = 123456emp.BossName = "Pointy-Haired Boss"

Two notable mentions (only 1 if you are doing C#) when comes to object declaration and initialization are still very valid.

关于对象声明和初始化的两个值得注意的提及(如果使用C#,则只有1个提及)仍然非常有效。

Fluent interface is a lot more than just initialization as you have seen in the 2 examples above.

流利的接口不只是初始化,如您在上面的两个示例中所看到的。

备选方案1 –对象初始化程序 (Alternative 1 – Object initializer)

Starting with .Net Framework 3.5 (Visual Studio 2008), after many years of C# developers (with many coming from the VB world) complained about the missing With statement, Microsoft released the object initializer as you can see in this example:

从.Net Framework 3.5(Visual Studio 2008)开始,经过多年的C#开发人员(其中许多来自VB世界)抱怨缺少With语句,Microsoft在此示例中发布了对象初始化器:

Dim emp2 As Employee = New Employee With {
.Name = "Eric Moreau", .Dob = New DateTime(1970, 5, 28), .HireDate = New DateTime(2007, 2, 1), .Salary = 123456, .BossName = "Pointy-Haired Boss"}

This syntax really helps shorten the initialization (and is of great help with collections) but won’t let you call methods!

这种语法确实有助于缩短初始化(并且对集合有很大帮助),但不会让您调用方法!

备选方案2 –带…结尾带(仅VB) (Alternative 2 – With … End With (VB only))

This VB-only syntax (that C# developers complained about) has been existing for years. Even before .Net. I have done VB since its version 4 (yes, I am that old) and I remember it was there.

这种C ++开发人员抱怨的仅VB语法已经存在多年了。 甚至在.Net之前。 我从VB版本4开始就做过(是的,我那年老),我记得它在那里。

The idea is to surround the statements as shown here:

这个想法是围绕如下所示的语句:

Dim emp3 As Employee = New EmployeeWith emp3    .Name = "Eric Moreau"    .Dob = New DateTime(1970, 5, 28)    .HireDate = New DateTime(2007, 2, 1)    .Salary = 123456    .BossName = "Pointy-Haired Boss"End With

Notice that this syntax is not only for object initialization has it works with both properties and methods.

请注意,此语法不仅适用于对象初始化,还适用于属性和方法。

返回Fluent界面 (Back to Fluent interface)

So how can we achieve something that would work with both properties and methods to get a fluent interface?

那么,我们如何才能实现既可以使用属性又可以使用方法来获得流畅接口的东西?

There won’t be a compiler trick or special keywords. You will need to write some methods in your classes to provide this feature. How much code? Well at least one method for everything you want to chain. It won’t be complex code. The syntax I prefer also requires an interface.

不会有编译器技巧或特殊关键字。 您将需要在类中编写一些方法来提供此功能。 多少代码? 对于要链接的所有内容,至少有一种方法。 它不会是复杂的代码。 我更喜欢的语法还需要一个接口。

基础班 (Basic class)

Look at this very simplified class just for the demo purpose:

请看这个非常简化的类,仅用于演示目的:

Public Class Employee    Public Name As String    Public Dob As Date    Public HireDate As Date    Public Salary As Int32    Public BossName As String    Public Overrides Function ToString() As String        Return String.Format(" The employee {0} was hired {1:D} with a salary of {2:c} reports to {3}. He was born on {4:D}", Name, HireDate, Salary, BossName, DOB)    End FunctionEnd Class

The ToString override is simply to ease the debugging.

ToString覆盖只是为了简化调试。

Let’s say we want to “fluentize” it.

假设我们要“使其流畅”。

“充实”课堂 (“Fluentize” the class)

The way I prefer (because if you dig, you might find other) requires an interface like this one

我喜欢的方式(因为如果您进行挖掘,您可能会发现其他方式)需要这样的界面

Public Interface IEmployeeFluent    Function OfName(ByVal pName As String) As IEmployeeFluent    Function AsOf(ByVal pDate As Date) As IEmployeeFluent    Function BornOn(ByVal pDate As Date) As IEmployeeFluent    Function SetSalary(ByVal pSalary As Int32) As IEmployeeFluent    Function ReportTo(ByVal pName As String) As IEmployeeFluentEnd Interface

In the previous section, my class was showing 5 properties. My interface here shows 5 methods, one for each property because I have decided so. It doesn’t have to be a 1-for-1 relation but it often makes sense.

在上一节中,我的班级展示了5个属性。 我的界面在这里显示5种方法,每种属性一个,因为我已经决定了。 它不必是一对一的关系,但通常很有意义。

Now that we have our interface, we need to implement it in the base class.

现在我们有了接口,我们需要在基类中实现它。

This is how I have implemented the interface for my class:

这是我为班级实现接口的方式:

Public Function OfName(ByVal pName As String) As IEmployeeFluent Implements IEmployeeFluent.OfName	Name = pName	Return MeEnd FunctionPublic Function AsOf(ByVal pDate As Date) As IEmployeeFluent Implements IEmployeeFluent.AsOf	HireDate = pDate	Return MeEnd FunctionPublic Function BornOn(ByVal pDate As Date) As IEmployeeFluent Implements IEmployeeFluent.BornOn	DOB = pDate	Return MeEnd FunctionPublic Function SetSalary(ByVal pSalary As Integer) As IEmployeeFluent Implements IEmployeeFluent.SetSalary	Salary = pSalary	Return MeEnd FunctionPublic Function ReportTo(ByVal pName As String) As IEmployeeFluent Implements IEmployeeFluent.ReportTo	BossName = pName	Return MeEnd Function

Simple no? The trick when we want to have a fluent interface is that each method will return the object on which it is working. It affects a property and returned the current instance. We can now use our new fluent object with something like this:

简单不? 当我们想要一个流畅的接口时,技巧是每个方法都将返回其正在运行的对象。 它影响一个属性并返回当前实例。 现在,我们可以将新的流畅对象与以下内容一起使用:

Dim emp2 As IEmployeeFluent = New Employee()MessageBox.Show(emp2.    OfName("Eric Moreau").    AsOf(New DateTime(2007, 2, 1)).    BornOn(New DateTime(1970, 5, 28)).    SetSalary(123456).    ReportTo("Pointy-Haired Boss").    ToString())

But usually, when we have a fluent interface, we don’t have to create an instance. Something in the chain will create one for us if we need to. This is why I have created a Shared method (static in C#) to return an instance of a new employee:

但是通常,当我们拥有一个流畅的界面时,我们不必创建一个实例。 如果需要,链中的某物将为我们创造一个。 这就是为什么我创建了一个Shared方法(在C#中为静态方法)以返回新员工的实例的原因:

Public Shared Function Hire() As IEmployeeFluent	Return New EmployeeEnd Function

Now that I have this Hire method, I don’t have to create an instance prior to call my chain of operations. Code will look like this:

现在有了此Hire方法,在调用操作链之前不必创建实例。 代码如下所示:

Dim emp As IEmployeeFluent = Employee.Hire().    OfName("Eric Moreau").    AsOf(New DateTime(2007, 2, 1)).    BornOn(New DateTime(1970, 5, 28)).    SetSalary(123456).    ReportTo("Pointy-Haired Boss")

You can chain as many methods as you want as long as they are all returning an instance of your object.

您可以根据需要链接任意数量的方法,只要它们都返回对象的实例即可。

The one exception is the last one. In a previous example, I have used MessageBox to show the employee data using the ToString method. This last method does not return an instance of an employee and we don’t really care as it is the last operation on the chain.

一个例外是最后一个例外。 在前面的示例中,我使用MessageBox通过ToString方法显示员工数据。 最后一个方法不返回雇员的实例,我们也不在乎,因为它是链上的最后一个操作。

调试 (Debugging)

Debugging can be harder as you now have a single line of code instead of multiple calls.

由于您现在只有一行代码而不是多个调用,因此调试会更加困难。

If you are the owner of the class, you can set a breakpoint in the fluent method and you will stop exactly where you want.

如果您是该类的所有者,则可以在fluent方法中设置一个断点,并且将在您想要的位置停止。

If you don’t have the code of that object, you will need to return to non-fluent method calls just for the sake of finding the issue.

如果没有该对象的代码,则仅为了发现问题就需要返回非流利的方法调用。

结论 (Conclusion)

As you have seen, adding a fluent interface to your existing classes is not a big deal but can makes your code a lot easier to read.

如您所见,在现有类中添加流畅的接口并不是什么大问题,但是可以使您的代码更易于阅读。

Fluent interface allows you to modify the API of your existing class with a more descriptive interface which improves its usability. At the same time, this preserves the current API interface and eliminates the risk of introducing bugs to code that is already implemented.

Fluent接口允许您使用更具描述性的接口来修改现有类的API,从而提高其可用性。 同时,这保留了当前的API接口,并消除了向已实现的代码引入错误的风险。

翻译自:

用界面创建.scr 文件

转载地址:http://egqzd.baihongyu.com/

你可能感兴趣的文章
Memcache存储大数据的问题
查看>>
HDU 5050 Divided Land(进制转换)
查看>>
python进阶学习笔记(三)
查看>>
javascript语法之Date对象与小案例
查看>>
Day45 jquery表格操作、轮播图
查看>>
POJ 2079 Triangle 旋转卡壳求最大三角形
查看>>
【模板】树链剖分
查看>>
计算机博弈研究——六子棋
查看>>
在Visualforce page中用自带的控件实现Ajax回调后台方法(并且可以用js去动态给parameters赋值)...
查看>>
Android驱动开发第七章
查看>>
ISO 9141-2 and ISO 14230-2 INITIALIZATION and DATA TRANSFER
查看>>
特征点检测--基于CNN:TILDE: A Temporally Invariant Learned DEtector
查看>>
CSS3_实现圆角效果box-shadow
查看>>
springboot集成Spring Session
查看>>
java-集合学习-底层实现
查看>>
android学习—— setContentView() 的前世今生
查看>>
CyclicBarrier和CountDownLatch笔记
查看>>
MySQL数据库基本操作
查看>>
commands 模块 分类: python 小练习 ...
查看>>
Ubuntu系统下配置PHP支持SQLServer 2005
查看>>