Свободный интерфейс C # с очередью или списком - PullRequest
2 голосов
/ 26 декабря 2011

У меня есть следующее:

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;
    }
}

Вот что я могу написать:

        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));

Что мне действительно не нравится, так это то, что я должен указать, какой тип IBehaviourЯ имею в виду каждый раз.Я хотел бы иметь возможность написать:

        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));

Есть ли у вас какие-либо идеи, что я должен написать, чтобы иметь возможность создавать базовый типизированный список и добавлять определенные элементы и свободно конфигурировать его?

Edit1: Удален некоторый код, чтобы избежать путаницы.Моя конечная цель - написать приведенный выше код.

Большое спасибо

1 Ответ

2 голосов
/ 26 декабря 2011

Измени это и возьми оттуда

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

Сделайте ваш тип класса конкретным, ограничьте тип, а затем просто удалите тип из ваших методов.

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: на основе комментариев

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

Edit2: больше на основе комментариев

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; }
}
...