如今,"流畅的界面"是一个相当热门的话题.C#3.0有一些很好的功能(特别是扩展方法)可以帮助你制作它们.
FYI,一个流畅的API意味着每个方法调用返回一些有用的东西,通常是你调用方法的同一个对象,所以你可以继续链接.Martin Fowler的与Java实例讨论它在这里.这个概念就像这样:
var myListOfPeople = new List(); var person = new Person(); person.SetFirstName("Douglas").SetLastName("Adams").SetAge(42).AddToList(myListOfPeople);
我在C#中看到了一些非常有用的流畅接口(一个例子是用于验证早先在我问过的StackOverflow问题中找到的参数的流畅方法.它让我感到震惊.它能够为表达参数验证规则提供高度可读的语法,并且另外,如果没有例外,它可以避免实例化任何对象!所以对于"正常情况",开销非常小.这一小窍门在短时间内教会了我很多.我想找到更多的东西像那样).
所以,我想通过观察和讨论一些优秀的例子来了解更多.那么,你在C#中制作或看到的一些优秀的流畅界面,是什么让它们如此有价值?
谢谢.
这实际上是我第一次听到"流畅的界面"这个词.但是我想到的两个例子是LINQ和不可变集合.
LINQ是一系列方法,其中大多数是扩展方法,至少需要一个IEnumerable并返回另一个IEnumerable.这允许非常强大的方法链接
var query = someCollection.Where(x => !x.IsBad).Select(x => x.Property1);
不可变类型,更具体地说,集合具有非常相似的模式.Immutable Collections返回一个新的集合,通常是一个变异操作.因此,构建集合通常会变成一系列链式方法调用.
var array = ImmutableCollection.Empty.Add(42).Add(13).Add(12);
对于方法参数验证的荣誉,您已经为我们的流畅API提供了新的想法.无论如何,我讨厌我们的前提条件检查......
我为开发中的新产品构建了一个可扩展性系统,您可以流畅地描述可用的命令,用户界面元素等.它运行在StructureMap和FluentNHibernate之上,它们也是很好的API.
MenuBarController mb; // ... mb.Add(Resources.FileMenu, x => { x.Executes(CommandNames.File); x.Menu .AddButton(Resources.FileNewCommandImage, Resources.FileNew, Resources.FileNewTip, y => y.Executes(CommandNames.FileNew)) .AddButton(null, Resources.FileOpen, Resources.FileOpenTip, y => { y.Executes(CommandNames.FileOpen); y.Menu .AddButton(Resources.FileOpenFileCommandImage, Resources.OpenFromFile, Resources.OpenFromFileTop, z => z.Executes(CommandNames.FileOpenFile)) .AddButton(Resources.FileOpenRecordCommandImage, Resources.OpenRecord, Resources.OpenRecordTip, z => z.Executes(CommandNames.FileOpenRecord)); }) .AddSeperator() .AddButton(null, Resources.FileClose, Resources.FileCloseTip, y => y.Executes(CommandNames.FileClose)) .AddSeperator(); // ... });
您可以配置所有可用的命令,如下所示:
Command(CommandNames.File) .Is() .AlwaysEnabled(); Command(CommandNames.FileNew) .Bind(Shortcut.CtrlN) .Is () .Enable(WorkspaceStatusProviderNames.DocumentFactoryRegistered); Command(CommandNames.FileSave) .Bind(Shortcut.CtrlS) .Enable(WorkspaceStatusProviderNames.DocumentOpen) .Is (); Command(CommandNames.FileSaveAs) .Bind(Shortcut.CtrlShiftS) .Enable(WorkspaceStatusProviderNames.DocumentOpen) .Is (); Command(CommandNames.FileOpen) .Is () .Enable(WorkspaceStatusProviderNames.DocumentFactoryRegistered); Command(CommandNames.FileOpenFile) .Bind(Shortcut.CtrlO) .Is () .Enable(WorkspaceStatusProviderNames.DocumentFactoryRegistered); Command(CommandNames.FileOpenRecord) .Bind(Shortcut.CtrlShiftO) .Is () .Enable(WorkspaceStatusProviderNames.DocumentFactoryRegistered);
我们的视图使用工作区为其提供的服务来配置标准编辑菜单命令的控件,他们只是告诉它观察它们:
Workspace .Observe(control1) .Observe(control2)
如果用户选中控件,则工作空间会自动为控件获取适当的适配器,并提供撤消/重做和剪贴板操作.
它帮助我们显着减少了设置代码,使其更具可读性.
我忘了告诉我们在WinForms MVP模型演示者中使用的库来验证视图:FluentValidation.真的很容易,真的可以测试,非常好!
我喜欢CuttingEdge.Conditions中流畅的界面.
从他们的样本:
// Check all preconditions: id.Requires("id") .IsNotNull() // throws ArgumentNullException on failure .IsInRange(1, 999) // ArgumentOutOfRangeException on failure .IsNotEqualTo(128); // throws ArgumentException on failure
我发现它更易于阅读,并且使我在检查方法中的前置条件(和后置条件)方面比我有50个if语句来处理相同的检查更有效.