简体   繁体   中英

Fluent C# Builder

Wanted to write some fluent like this...

new Actor().DoSomething<Type>().WithOption(options).When(Conditions);

I understand method chaining and how to pass action to subsequent method / object.

For example, action of DoSomething will be passed to object containing WithOption method and action of withOption passed to the object containing When method.

It could be something like

interface Actor {
  ActorOption DoSomething<T>();
}

interface ActorOption {
  ActorCondition WithOption();
}

interface ActorCondition{
  void When();
}

So actual action happens in WHen method. All are fine so far.

To execute the code with default option or no condition, it could be called as new Actor.DoSomething<T>().WithDefaultOption().Always();

My worry is what if someone leaves the code in middle, which means new Actor.DoSomething<T>() . It appears the actor is supposed to do something, which is fluently right.

I am not able to think of design which can cover similar scenario. Please suggest.

PS: I am writing wrapper over some third party class, so I do not have full control on internal implementation. For example, I cannot set condition once options are set or vice versa.

if you write

new Actor().DoSomething<Type>().WithOption(options).When(Conditions);

You could write alternative:

Actor actor = new Actor();
doResult = actor.DoSomething<Type>();
optionResult = doResult.WithOption(options);
conditionResult = optionResult.When(Conditions);

So you can see that your options and your condition added after you execute DoSomething, so it have no effect for the method DoSomething. If you execute your code finally in the When method, it is not intuitive. Better you prepare your actor and get your result with executing DoSomething() ("lamda-style").

And if someone leave some method calls.. Yeah of course then its missing... If it is necessary, you have to add it as a parameter in DoSomething. If not, you have to define default options, which are used if no options specified.

The actual action shouldn't happen in the When method. Instead, try making your fluent interface so that the last method "does something":

new Actor<Type>().WithOption(options).When(Conditions).DoSomething();

So your actor will be configured first and then run. If you don't like this syntax, you can still go for something like:

new Actor().DoSomething(config => config.WithOption(options).When(conditions));

there are several method of monad Maybe, they should help you.

public static class Maybe
{
    public static TResult With<TInput, TResult>
        (this TInput o, Func<TInput, TResult> evaluator)
        where TInput : class where TResult : class
    {
        return o == null ? null : evaluetor(o);
    }

    public static TResult Return<TInput, TResult>
        (this TInput o, Func<TInput, TResult> evaluator, TResult failureValue)
        where TInput : class
    {
        return o == null ? failureValue : evaluator(o);
    }

    public static bool ReturnSuccess<TInput>(this TInput o)
        where TInput : class
    {
        return o != null;
    }

    public static TInput If<TInput>(this TInput o, Predicate<TInput> evaluator)
        where TInput : class
    {
        if (o == null)
            return null;
        return evaluator(o) ? o : null;
    }

    public static TInput Do<TInput>(this TInput o, Action<TInput> action)
        where TInput : class
    {
        if (o == null) return null;
        action(o);
        return o;
    }
    public static TInput If<TInput>(this TInput o, Func<TInput, bool> evaluator)
        where TInput : class
    {
        if (o == null) return null;
        return evaluator(o) ? o : null;
    }        
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM