对象的循环传递

时间:2015-10-24 06:41:29

标签: c# design-patterns flow cyclic

我正在尝试模拟血流量。就像它得到的一样简单我试图让一个事件(TimerTick)触发资源对象从单元A到单元B,B到C,C到A的传输。我似乎无法从中重复传输资源一次迭代到另一次,我尝试了很多不同的方式,而不是下面粘贴的方式。 这些单元在施工后以三角形连接。我知道这会让第一个单元出错,并且已经尝试了很多方法来处理它(我不确定这是否是唯一的问题)但是由于没有工作,我不会发布它们。 任何一个单位不需要知道任何其他单位的事件设置的想法将完全被赞赏。但只是一种方法来完成这项工作也将受到赞赏。

class Unit{    
Resource currentResource;
Resource incomingResource;
Unit preUnit;
Unit postUnit;
public Unit( int resource, Timer t)
    {
        this.currentResource = new Resource(resource);
        t.TimerTick += T_TimerTick;
    }
 private void T_TimerTick(object sender, TimerTickEventArgs e)
    {
        postUnit.receiveResource(currentResource);
        currentResource = incomingResource;
}
void receiveResource(Resource resource)
    {
        incomingResource = resource;
    }
//pre and post units connected appropriately to Cycle ...-A-B-C-A-...
// with one cycle per TimerTick
}

2 个答案:

答案 0 :(得分:0)

那些名为Unit的元素和方法是否也在一个名为Unit?

的类中

尝试将方法和元素移动到另一个类。

我会为你的单位制作三个静态类:

public static class UnitA
{
    var foo1;
    var foo2;
}

public static class UnitB
{
    var foo1;
    var foo2;
}

public static class UnitC
{
    var foo1;
    var foo2;
}

对于每个tic,您可以处理来自任何其他类的资源:

FooHandler_Tick
{
    // Store C's content.
    var tempFoo1 = UnitC.foo1;
    var tempFoo2 = UnitC.foo2;

    // B to C.
    UnitC.foo1 = UnitB.foo1;
    UnitC.foo2 = UnitB.foo2;

    // A to B.
    UnitB.foo1 = UnitA.foo1;
    UnitB.foo2 = UnitA.foo2;

    // C to A.
    UnitC.foo1 = tempFoo1;
    UnitC.foo2 = tempFoo2;
}

这适用于您的项目吗?

答案 1 :(得分:0)

我建议用Observer模式反转控制

这是一个工作设置,以解释我的建议。在我的代码中,每个单元只是将资源增加1.

并生成以下输出

*启动单位A值1

单位A,输出1

单元B,输入1

单位B,输出2

单位C,输入2

单位C,输出3

单元A,输入3

单元A,循环完成*

客户端代码

      IInitiatorUnit A = new InitiatorUnit("A");
        IUnit B = new Unit("B");
        IUnit C = new Unit("C");

        B.RegisterUnit(A); // B is listening to A
        C.RegisterUnit(B); // C is listening to B
        A.RegisterUnit(C); //  A is listinig to C


 void heartBeatTimer_Tick(object sender, EventArgs e)
    {
        A.GenerateResource(1); // Start the process
    }

我设计了一个单元,它需要输入,处理它和它。发起

事件
     interface IUnit
    {
        event EventHandler<ResourceGeneratedEventArgs> ResourceGenerated;
        void RegisterUnit(IUnit inputUnit);
        string Name { get; }
    }

    class Unit : IUnit
    {

        IUnit mInputUnit;
        public event EventHandler<ResourceGeneratedEventArgs> ResourceGenerated;
        public string Name { get; private set; }

        public Unit(string name)
        {
            this.Name = name;
        }

        public void RegisterUnit(IUnit inputUnit)
        {
            this.mInputUnit = inputUnit;
            this.mInputUnit.ResourceGenerated += mInputUnitResourceGenrated;
        }

        void mInputUnitResourceGenrated(object sender, ResourceGeneratedEventArgs inputResource)
        {
           //take the input resorce. pocess it & fire the event;
            //I'm just adding 1 to it as sample

            int outputResource = inputResource.Resource + 1;

            Console.WriteLine("Unit {0}, input {1} ", this.Name, inputResource.Resource, outputResource);

            OnResourceGenerated(outputResource);
        }      

        protected virtual void OnResourceGenerated(int outputResource)
        {
            Console.WriteLine("Unit {0}, output {1}", this.Name,  outputResource);

             if (ResourceGenerated != null)
                ResourceGenerated(this, new ResourceGeneratedEventArgs(outputResource));
        }
    }


    public class ResourceGeneratedEventArgs : EventArgs
    {
        public ResourceGeneratedEventArgs(int resource)
        {
            Resource = resource;
        }

        public int Resource { get; private set; }
    } 



     /// <summary>
     /// This is just to start the process here, Nothing great here 
     /// </summary>
     interface IInitiatorUnit : IUnit
     {
        void  GenerateResource(int initialValue);
     }


    class InitiatorUnit : Unit, IInitiatorUnit
    {
        //prevents the cycle from going on & on
        bool resetFlag;

        public InitiatorUnit(string name):base(name)
        {

        }

        public void GenerateResource(int initialValue)
        {
            resetFlag = false;
            Console.WriteLine("Initiating Unit {0} value {1}", this.Name, initialValue);
            OnResourceGenerated(initialValue);
        }

        protected override void OnResourceGenerated(int outputResource)
        {
            //Dont raise the event. if the cycle has completed
            if (resetFlag == false)
            {
                resetFlag = true;
                base.OnResourceGenerated(outputResource);
            }
            else
            {
                //do nothing, cycle has completed
                Console.WriteLine("Unit {0}, Cycle complete", this.Name);
            }
        }
    }

编辑1:接近非常多的单位

在我的第一种方法中,每个单位称后续的一个创建一个链,就像这样 - enter image description here

由于节点会增加,因此调用堆栈的深度也会增加,因此当数量达到数千时,我们可以超出堆栈限制,从而导致堆栈溢出。

因此,新方法只是在单元上使用迭代,为每个单元提供请求,获得响应并将响应作为请求提供给后续单元。像这样的东西 -

enter image description here

这是一个工作样本&amp;它会生成以下输出 -

单位A,输入0 单元A,输出1 单元B,输入1 单元B,输出2 单元C,输入2 单位C,输出3 循环完成结果3

客户代码

private void ClientCode()
    {
        // Create an array of units 
        IUnit[] units = new IUnit[] {
            new Unit("A"), // A will be called 1st . It needs to be given an initial value to start processing
            new Unit("B"), // B will get A's Output to process. 
            new Unit("C"), // C will get B's Output to process. 
        };

        // pass the array to workflow to process 
        cycle = new WorkFlow(units);

        Console.ReadLine();
    }

心跳计时器

  void heartBeatTimer_Tick(object sender, EventArgs e)
    {
        var result = cycle.Execute(new Resource(0)); // starting the cycle with initial value of 0

        Console.WriteLine("Cycle completed result {0}", result.Value); 
    }

现在基础设施要简单得多,

    interface IUnit
    {
        Resource ProcessResource(Resource inputResource);
        string Name { get; }
    }

    class Unit : IUnit
    {
        public string Name { get; private set; }

        public Unit(string name)
        {
            this.Name = name;
        }

        public Resource ProcessResource(Resource inputResource)
        {
            //take the input resorce. pocess it & fire the event;
            //I'm just adding 1 to it as sample

            int outputResource = inputResource.Value + 1;

            Console.WriteLine("Unit {0}, input {1} ", this.Name, inputResource.Value);
            Console.WriteLine("Unit {0}, output {1} ", this.Name, outputResource);


            return new Resource(outputResource);
        }
    }


    class WorkFlow
    {
        IUnit[] mUnits;

        public WorkFlow(IUnit[] units)
        {
            this.mUnits = units;
        }

        public Resource Execute(Resource initiatingResource)
        {
            Resource result = initiatingResource; // initialise result with the input of the cycle.
            for (int i = 0; i < mUnits.Length; i++)
            {
                // the result is passed as input. 
                //IUnit.ProcessResource function gives back a new result which is encached as input for subsequent resource
                result = mUnits[i].ProcessResource(result);
            }
            return result; // after all are processed, 
        }
    }

    public class Resource
    {
        public Resource(int resourceValue)
        {
            Value = resourceValue;
        }

        public int Value { get; private set; }
    }  
希望所有人现在都能正常工作。如果有任何不清楚的地方,请给我发表评论。