Tips for writing fluent interfaces in C# 3

前端 未结 8 1688
借酒劲吻你
借酒劲吻你 2020-12-07 11:39

I\'m after some good tips for fluent interfaces in C#. I\'m just learning about it myself but keen to hear what others think outside of the articles I am reading. In particu

相关标签:
8条回答
  • 2020-12-07 11:45

    And on your 2nd and 3rd question;

    Three fluent patterns i've noticed

    The first uses the using statement (C# 2.0) to run code in a certain context for example:

    using(var transaction = new Transaction())
    {
      // ..
      // ..
    }
    

    This uses the constructor and disposer of Transaction to set up a transaction and then runs the code in this context.

    The second does almost the same but with lambda's, this is used a lot in Rhino Mocks for example.

    (new Transaction()).Run( () => mycode(); );
    

    The best known fluent interface is to use return types to chain method calls. Mostly methods return this so you can chain calls on the same object. But you can also return different objects to change the context depending on the method called. If you've got an object that can only run in a transaction (sorry can't think of a different example) you can give it a StartTransaction method that returns an initialized transaction where you can run call run and stoptransaction, in pseudocode:

    class Runner
    {
      Transaction StartTransaction()
      {
        return new Transaction(this);
      }
    }
    
    class Transaction
    {
      Transaction Run()
      Transaction StopTransaction()
    }
    

    where the call looks like

    var runner = new Runner();
    runner
      .StartTransaction()
      .Run()
      .StopTransaction();
    

    Of course you need to add all kinds of error handling etc.

    0 讨论(0)
  • 2020-12-07 11:49

    Sometime ago I had the same doubts you are having now. I've done some research and now I'm writing some posts to help in those topics.

    Check it at my blog:

    Guidelines to Fluent Interface design in C# part 1

    And in the following posts I will cover every one of the points you mentioned.

    Best regards André Vianna

    0 讨论(0)
  • 2020-12-07 11:50

    The single biggest challenge I have experienced as a consumer of fluent interfaces is that most of them aren't really fluent intefaces -- instead they are really instances of what I tend to refer to as 'legible interfaces'.

    A fluent interface implies that its primary goal is to make it easy to SPEAK it whereas a legible interface implies that its primary goal is to be easy to READ it. Most fluent interfaces only tend to be ridiculously difficult to code with but conversely incredibly easy to READ later by others.

    Assert().That().This(actual).Is().Equal().To(expected).
        Except().If(x => x.GreaterThan(10));
    

    ...is alot easier to read later than it is to actually compose in code!

    0 讨论(0)
  • 2020-12-07 11:50

    One thing is that you have to account for the morphology of English syntax and ensure that you have not introduced undocumented sequential coupling underneath.

    // Snarky employees get a raise.
    employees.WhereSnarky().GiveRaise();
    

    vs.

    // Depending on implementation, everyone may get a raise.
    employees.GiveRaise().WhereSnarky();
    
    0 讨论(0)
  • 2020-12-07 11:56

    You'll hit a brick when using inheritance along with fluent interfaces because using polymorphic methods break your call chains and you definitely don't want to make your interfaces non-fluent by using ugly casting and paranthesis where they are not needed. I've written an article about a pattern that provides you with a workaround using generic builders and generic extension methods with generic constraints: http://liviutrifoi.wordpress.com/2009/02/16/fluent-interfaces-constraints-at-compile-time/

    0 讨论(0)
  • 2020-12-07 12:02

    Moq hides unreleated methods such as equals, ToString and so on to make their fluent interface even easier to use.

    Hiding System Object is an article explaining the benefit of doing this.

    0 讨论(0)
提交回复
热议问题