【问题标题】:C# Fluent Interface With Queue or List带有队列或列​​表的 C# Fluent 接口
【发布时间】:2011-12-26 12:33:25
【问题描述】:

我有以下:

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:删除了一些代码以避免混淆。我的最终目标是编写上面的代码。

非常感谢

【问题讨论】:

标签: c# queue covariance fluent-interface


【解决方案1】:

改变它并从那里拿走它

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:基于 cmets

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

Edit2:更多基于 cmets

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

【讨论】:

  • 我需要能够选择要添加的行为,但您的解决方案不允许我这样做,因为您从 AddBehaviour 中删除了该类型。您的代码不允许我编写 queue.AddBehaviour()。队列不应该是特定类型的,因为我可以根据需要添加尽可能多的不同类型的行为。
  • 所有这些行为都实现了 IBehaviour 吗?如果是这样,我看不出代码有问题,只需将 T 替换为 IBehaviour 即可。
  • 您的代码将要求我将队列完全键入到 IBehaviourB 或 IBehaviourA。队列只需为 IBehaviour,这样我就可以添加 IBehaviourA 或 IBehaviourB,而不必在 ConfigureFor 和 WhenComplete 方法中指定类型。
  • 查看我的 Edit1 以获得可能的解决方案
  • 另一件事是您的 BehaviourQueue 实现与您的接口 IBehaviourQueue 不匹配。您是否在 AddBehaviour 上指定了 not T。最终你必须这样做,否则你无法决定要注入哪种类型。所以我不确定你的编辑解决方案基于什么代码。
猜你喜欢
  • 2014-01-24
  • 2021-06-26
  • 1970-01-01
  • 2020-07-19
  • 1970-01-01
  • 1970-01-01
  • 2018-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多