标签: fluent-interface

流畅的界面和漏洞抽象

什么是流畅的界面?我找不到一个好的定义,但我得到的只是我不熟悉的语言中的长代码示例(例如C++).

另外,什么是漏洞抽象?

谢谢

oop fluent-interface leaky-abstraction

13
推荐指数
4
解决办法
1798
查看次数

流畅的API - 返回这个还是新的?

我最近提出了一个有趣的问题,流利的方法应该返回什么?他们应该改变当前对象的状态还是创建一个具有新状态的全新对象?

如果这个简短描述不是非常直观,这是一个(不幸的)冗长的例子.这是一个计算器.它执行非常繁重的计算,这就是他通过异步回调返回结果的原因:

public interface ICalculator {
    // because calcualations are too lengthy and run in separate thread
    // these methods do not return values directly, but do a callback
    // defined in IFluentParams
    void Add(); 
    void Mult();
    // ... and so on
}
Run Code Online (Sandbox Code Playgroud)

所以,这是一个设置参数和回调的流畅界面:

public interface IFluentParams {
    IFluentParams WithA(int a);
    IFluentParams WithB(int b);
    IFluentParams WithReturnMethod(Action<int> callback);
    ICalculator GetCalculator();
}
Run Code Online (Sandbox Code Playgroud)

这个接口实现有两个有趣的选项.我将展示它们,然后我会写出我发现它们各自的好坏.

因此,首先是普通,它返回:

public class FluentThisCalc : IFluentParams {
    private int? _a;
    private int? _b;
    private Action<int> _callback;

    public …
Run Code Online (Sandbox Code Playgroud)

c# java oop design-patterns fluent-interface

13
推荐指数
1
解决办法
1420
查看次数

无法确定关联的主要端 - 实体框架模型优先

我在Visual Studio中创建了实体数据模型.现在我有一个SQL查询文件和从Model生成的C#类.

题:

生成的类没有注释或代码(Fluent API).可以吗?我试图运行我的应用程序但抛出了异常:

无法确定类型"Runnection.Models.Address"和"Runnection.Models.User"之间关联的主要结尾.必须使用关系流畅API或数据注释显式配置此关联的主要结尾.

我读到我不能将Fluent API与"Model First"一起使用.那我该怎么办?

码:

用户

public partial class User
{
    public User()
    {
        this.Events = new HashSet<Event>();
        this.CreatedEvents = new HashSet<Event>();
    }

    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Photo { get; set; }
    public int EventId { get; set; }
    public string Nickname { get; set; }
    public OwnerType OwnerType { get; set; }
    public NetworkPlaceType PlaceType …
Run Code Online (Sandbox Code Playgroud)

c# entity-framework fluent-interface

13
推荐指数
1
解决办法
4万
查看次数

如何做PHP嵌套类或嵌套方法?

我怎么能用PHP做到这一点

$myDBClass->users()->limit(5);//output you limited users to 5
$myDBClass->comments()->limit(3);//output you limited comments to 3
Run Code Online (Sandbox Code Playgroud)

我的意思是嵌套方法或嵌套类(我不知道!)所以当我将limit方法作为用户的子进程调用时,它会知道我从"users"方法调用它 - 或者 - 当我调用时限制方法 - 或类! - 来自评论它也知道.

PHP类可能的结构是什么?


这个问题的原因是因为我在自己的数据库类上工作所以我可以很容易地使用这样的东西

     $DB->comments()->id(" > 3")->limit(10);
Run Code Online (Sandbox Code Playgroud)

生成sql代码"select*from comments where id> 3 limit 10"谢谢

php design-patterns fluent-interface

12
推荐指数
2
解决办法
2万
查看次数

包含方法名称末尾的介词是否遵循或减损了正常的C#API设计?

我知道这听起来像是一个主观的答案,但我会尽量使问题尽可能客观,因为对这个问题的客观答案将是最有帮助的.

我最近有一位代码审查员指出,我习惯在我的方法结束时加入介词.这是我作为类的扩展方法编写的最新方法Point:

var rectangle = new Rectangle(0, 0, 2, 2);
var point = new Point(3, 1);

var result = point.DistanceTo(rectangle);
Run Code Online (Sandbox Code Playgroud)

我的代码审查员提到该方法应该point.Distance(rectangle).我一直认为这是主观的,也是风格问题.但是,我注意到更多的.NET API设计朝这个方向发展.例如,使用NUnit的Fluent Interface,您可以:

Assert.That(result, Is.EqualTo(1.0));
Run Code Online (Sandbox Code Playgroud)

我也和Linq见过这个:

list.CopyTo(anotherList);
list.IndexOf(item);
list.RemoveAt(0);
Run Code Online (Sandbox Code Playgroud)

.NET和/或第三方API设计人员在方法结束时使用介词是否有任何稳定或一致的方式?或者只是风格和主观问题?.NET框架中的API设计本身是否随着此策略发展,或者它是否始终存在?

c# fluent-interface naming-conventions

12
推荐指数
2
解决办法
1787
查看次数

没有使用泛型扩展方法的类型推断

我有以下方法:

public static TEventInvocatorParameters Until
    <TEventInvocatorParameters, TEventArgs>(this TEventInvocatorParameters p,
                                            Func<TEventArgs, bool> breakCond)
    where TEventInvocatorParameters : EventInvocatorParameters<TEventArgs>
    where TEventArgs : EventArgs
{
    p.BreakCondition = breakCond;
    return p;
}
Run Code Online (Sandbox Code Playgroud)

而这堂课

public class EventInvocatorParameters<T>
    where T : EventArgs
{
    public Func<T, bool> BreakCondition { get; set; }
    // Other properties used below omitted for brevity.
}
Run Code Online (Sandbox Code Playgroud)

现在,我有以下问题:

  1. 此扩展方法甚至可以显示所有类型string.
  2. 我不能写new EventInvocatorParameters<EventArgs>(EventABC).Until(e => false);它告诉我"方法的类型参数......不能从用法中推断出来."

我不能使用像这样的泛型类型参数吗?你会如何解决这个问题?
重点:我需要这两个通用参数,因为我需要返回调用此扩展方法的相同类型.


更广泛的图片(没有必要回答问题!):
我正在尝试创建一个流畅的界面来调用事件.基础是这个静态类:

public static class Fire
{
   public static void Event<TEventArgs>(
       ConfiguredEventInvocatorParameters<TEventArgs> parameters)
    where TEventArgs …
Run Code Online (Sandbox Code Playgroud)

.net c# generics extension-methods fluent-interface

12
推荐指数
2
解决办法
2889
查看次数

Entity Framework Code First是否允许在单独的文件中进行流畅的映射?

我正在使用Entity Framework Code First开发一个相当大的数据库模式.我更喜欢Fluent API而不是Data Annotations方法,因为它将我的域对象保留为简单的POCO.

为了使用Fluent API,我必须在继承自DbContext的类中重写OnModelCreating.

我不喜欢所有实体的所有映射都在这个方法中.我之前使用过类似FluentNHibernate的东西,每个实体都有自己的映射类.EF有类似的东西吗?

我想我可以创建自己的接口来实现一个映射类,并在OnModelCreating方法中调用它们.我可以使用反射或IoC来发现它们.我并没有特别看到这种方法有什么问题,但我想知道Entity Framework是否已经开箱即用了这样的东西?

entity-framework fluent-interface ef-code-first

12
推荐指数
1
解决办法
4317
查看次数

用于流畅API的类型推断

我有以下扩展方法:

public static IFoo Foo(this IFluentApi api, Action action);

public static IFoo<TResult> Foo<TResult>(
    this IFluentApi api, Func<TResult> func);

public static IBar Bar(this IFoo foo);

public static void FooBar(this IBar bar, Action action);

public static void FooBar<TResult>( // <- this one cannot work as desired 
    this IBar bar, Action<TResult> action);
Run Code Online (Sandbox Code Playgroud)

通用接口始终从其对应的非通用接口派生.

不幸的是,为了使这项工作:

api.Foo(x => ReturnLong())
   .Bar()
   .FooBar(x => ...); // x should be of type long
Run Code Online (Sandbox Code Playgroud)

我还需要实现以下扩展方法:

public static IBar<TResult> Bar<TResult> (this IFoo<TResult> foo);
Run Code Online (Sandbox Code Playgroud)

并将上述最后一个扩展方法更改为:

public static void FooBar<TResult>(
    this IBar<TResult> …
Run Code Online (Sandbox Code Playgroud)

c# generics fluent-interface fluent

12
推荐指数
1
解决办法
599
查看次数

确保调用以结束一系列方法

注意/免责声明:经过几次搜索后,我在本帖中看到的最接近的内容是关于SO的帖子(方法链接和整理问题),这与我的问题相似,但并没有真正回答 - 但无论如何,我希望这不是一个重复的问题.

我在做什么:

我已经在一个方法调用的现有日志框架上创建了一个流畅的接口作为一个外观 - 所以我的语法看起来有点像这样:

Logger.Debug().Message("Debug message!").WriteToLog();
Logger.Error().Message("An exception occured").Exception(ex).WriteToLog();
Run Code Online (Sandbox Code Playgroud)

我将一个内部对象从一个方法调用传递给下一个对象,以便在最后调用时(WriteToLog方法); 消息被写入某个日志文件.

我觉得有点闻

为了验证(仅当应用程序是在调试模式下构建的时候),我在上下文类(只是属性包对象)上有一个属性,它从方法调用传递给返回的对象,直到链终止; 它是一个布尔值,默认为false.

使用Debug.Assert在上下文类析构函数中评估此属性,以确定是否调用结束链的最终方法,以便在开发期间捕获任何日志记录错误.(属性,设置属性的代码和析构函数本身都是在#if DEBUG预处理器指令的上下文中创建的,所以如果它是在发行版中构建的,或者如果符号不存在,则代码不会得到编译.)

知道在c#2.0及更高版本中使用析构函数是不好的,并且我可能无法访问属性,因为我相信对终结顺序没有任何保证.这就是为什么它只在内置调试模式时发生,以及为什么我想摆脱它.

我试图建立一个断言的原因是因为它很容易忘记并最终编写代码

Logger.Debug().Message("Debug message!");
Run Code Online (Sandbox Code Playgroud)

这意味着没有任何东西被记录下来,虽然粗略地看了一眼就好了.

我的问题

我想知道的是 - 有人能想到另一种验证最终方法总是被调用的方法吗?在开发过程中只需要这些消息,以向开发人员强调方法链尚未完成 - 我不希望最终用户找到与登录最终产品相关的错误消息.

.net c# fluent-interface

11
推荐指数
1
解决办法
1092
查看次数

如何创建流畅的查询界面?

我知道如何链接类方法(使用"return $ this"和all),但我想要做的是以聪明的方式链接它们,看看这个:

$albums = $db->select('albums')->where('x', '>', '20')->limit(2)->order('desc');
Run Code Online (Sandbox Code Playgroud)

我从这个代码示例中可以理解的是,前3个方法(select,where,limit)构建将要执行的查询语句,最后一个(order)来完成语句然后执行它并返回结果吧?

但是,事实并非如此,因为我可以轻松地删除任何这些方法(当然除了"选择")或者 - 更重要的是 - 改变他们的顺序,什么都不会出错!! 这意味着方法"选择"处理工作,对吗?那么在调用方法"select"之后,其他3个方法如何添加/影响查询语句!

php oop fluent-interface

11
推荐指数
1
解决办法
4363
查看次数