JeanT
JeanT

Reputation: 1359

C# Fluent Interface With Queue or List

I have the following :

public interface IBehaviour
{
    event EventHandler Completed;
    void Execute();
}

public interface IBehaviourA : IBehaviour
{
    // Some specific stuff here
    object A { get; set; }
}

public interface IBehaviourB : IBehaviour
{
    // Some specific stuff here
    object B {get;set;}
}

public interface IBehaviourQueue
{
    void Run();
    BehaviourQueueItem<IBehaviour> AddBehaviour<T>() where T : IBehaviour;
}

public class BehaviourQueue : Queue<BehaviourQueueItem<IBehaviour>>,  IBehaviourQueue
{
    private IBehaviourFactory factory;

    public BehaviourQueue(IBehaviourFactory factory)
    {
        this.factory = factory;
    }

    public BehaviourQueueItem<IBehaviour> AddBehaviour<T>() where T:IBehaviour
    {
        T behaviour = factory.GetNew<T>();
        var queueItem = new BehaviourQueueItem<IBehaviour>(behaviour);
        Enqueue(queueItem); 
        return queueItem;
    }

    public void Run()
    {
        //Run each queue item
    }

}

public class BehaviourQueueItem<T>
{
    public IBehaviour behaviour;
    public BehaviourQueueItem(IBehaviour behaviour)
    {
        this.behaviour = behaviour;
    }
    public void WhenComplete(Func<T, bool> action) 
    {
        CompletedAction = action;
    }

    public BehaviourQueueItem<T> ConfigureFor<Z>(Action<Z> dow) where Z : IBehaviour
    {
        dow((Z)behaviour);
        return this;
    }
}

Here is what I can write :

        var q =new BehaviourQueue(new BehaviourFactory());
        q
             .AddBehaviour<IBehaviourA>()
             .ConfigureFor<IBehaviourA>(x => x.A = "someValueA")
             .WhenComplete(x => DoStuffWithSomeProperty(((IBehaviourA)x).A));
        q
             .AddBehaviour<IBehaviourB >()
             .ConfigureFor<IBehaviourB >(x => x.B = "someValueB")
             .WhenComplete(x => DoStuffWithSomeProperty(((IBehaviourB)x).B));

What I don't really like is that I have to specify which type of IBehaviour I am referring to everytime. I would like to be able to write :

        var q =new BehaviourQueue(new BehaviourFactory()); // Queue here is of IBehaviour
        q
             .AddBehaviour<IBehaviourA>()
             .Configure(x => x.A = "someValueA")
             .WhenComplete(x => DoStuffWithSomeProperty(x.A));
        q
             .AddBehaviour<IBehaviourB>()
             .Configure(x => x.B = "someValueB")
             .WhenComplete(x => DoStuffWithSomeProperty(x.B));

Do you have any idea what I should write to be able to create a base typed list and add specific items and configuring it fluently ?

Edit1: Removed some code to avoid confusion. My ultimate goal is to write the above code.

Many thanks

Upvotes: 2

Views: 528

Answers (1)

Tomislav Markovski
Tomislav Markovski

Reputation: 12346

Change this and take it from there

public interface IBehaviourQueue<T> where T : IBehaviour
{
    void Run();
    BehaviourQueueItem<T> AddBehaviour<T>() where T
}

Make your class type specific, constrain the type and then just remove the type from your methods.

public class BehaviourQueue<T> : Queue<BehaviourQueueItem<T>>,  IBehaviourQueue<T> where T : IBehaviour
{
    private IBehaviourFactory factory;

    public BehaviourQueue(IBehaviourFactory factory)
    {
        this.factory = factory;
    }

    public BehaviourQueueItem<T> AddBehaviour()
    {
        T behaviour = factory.GetNew<T>();
        var queueItem = new BehaviourQueueItem<T>(behaviour);
        Enqueue(queueItem); 
        return queueItem;
    }

    public void Run()
    {
        //Run each queue item
    }

}

Edit1: based on comments

public BehaviourQueueItem<T> ConfigureFor(Action<IBehaviour> dow)
{
    dow(behaviour);
    return this;
}

Edit2: more based on comments

public class BehaviourQueueItem<T>
{
    public T behaviour;
    public BehaviourQueueItem(T behaviour)
    {
        this.behaviour = behaviour;
    }
    public void WhenComplete(Func<T, bool> action)
    {
        CompletedAction = action;
    }

    public BehaviourQueueItem<T> ConfigureFor(Action<T> dow)
    {
        dow(behaviour);
        return this;
    }

    public Func<T, bool> CompletedAction { get; set; }
}

Upvotes: 2

Related Questions