【问题标题】:Eliminating circular dependency and create object消除循环依赖并创建对象
【发布时间】:2014-10-15 22:19:53
【问题描述】:

我的解决方案中有三个项目

  • ClassLibrary => 参考 InterfaceLibrary, UIProject 包含(CountDownTimer.cs)

  • 接口库 包含 (ICountDownTimer.cs)

  • UIProject => 参考接口库 包含(frmMain.cs,Controller.cs)

我已经读到添加接口是一种消除循环依赖的方法,我试图找到我的问题的答案,但一直没有得到解决。

我需要在控制器类中创建一个新的 CountDownTimer 对象,请任何人提供建议或帮助

public partial class frmMain : Form
{
    //Reference to the Controller class, so we can call it
    private Controller MController { get; set; }

    //Constructor
    public frmMain(Controller cntr)
    {
        MController = cntr;
        InitializeComponent();
    }

    private void frmMain_FormClosed(object sender, FormClosedEventArgs e)
    {
        //Because controller is the main class, closing the form won't exit the program
        //So we need to close it with an exit call
        Application.Exit();
    }

    private void btn_Start_Click(object sender, EventArgs e)
    {
        MController.StartTimer();
    }
}


public class Controller : ApplicationContext
{
    //Store a reference to the UI
    internal frmMain MainUI { get; set;}
    private ICountDownTimer timer;

    public Controller()
    {

        MainUI = new frmMain(this);
        MainUI.Show();
    }

    internal void StartTimer()
    {

    }
}

public class CountDownTimer : ICountDownTimer
    {
        private int seconds; // Time in seconds
        private int reSetValue; // Time in seconds
        private System.Windows.Forms.Timer timer1;
        private Controller parent;

        public CountDownTimer(Controller parent, int seconds)
        {
            this.parent = parent;
            this.seconds = seconds;
            reSetValue = seconds;

            timer1 = new System.Windows.Forms.Timer();
            timer1.Tick += new EventHandler(timer1_Tick); // Add Handler(timer1_Tick)
            timer1.Interval = 1000; // 1 second

            //parent.TickUpdate(("" + seconds / 60).PadLeft(2, '0') + "m:" + ("" + seconds % 60).PadLeft(2, '0') + "s");
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            seconds--; // Decrement seconds
            if (seconds == 0) // Stop Timer at 0
            {
                timer1.Stop(); // Stop timer
            }
            else
            {
                //parent.TickUpdate(convertSecondToMMSS());

                if (seconds % 60 == 0 || seconds >= 1 && seconds <= 10)
                {
                    //parent.TickUpdate(seconds);
                }
            }
        }

        void ICountDownTimer.StartTimer()
        {
            timer1.Start(); // Start Timer
        }

        public string convertSecondToMMSS()
        {
            TimeSpan t = TimeSpan.FromSeconds(seconds);
            string str = string.Format("{0:D2}m:{1:D2}s",
                t.Minutes,
                t.Seconds);

            return str;
        }

        void ICountDownTimer.StopTimer()
        {
            timer1.Stop();
        }

        void ICountDownTimer.ResetTimer()
        {
            timer1.Stop();
            seconds = reSetValue;
            //parent.TickUpdate(convertSecondToMMSS());
        }

        void ICountDownTimer.SetTimer(int seconds)
        {
            timer1.Stop();
            this.seconds = seconds;
            reSetValue = seconds;
            //parent.TickUpdate(convertSecondToMMSS());
        }
    }

public interface ICountDownTimer
{
    void StartTimer();

    void StopTimer();

    void ResetTimer();

    void SetTimer(int seconds);
}

【问题讨论】:

  • 我在这里可能是少数,但我从来没有理由将接口与它们的实现放在一个单独的项目中,除非在某些地方添加了 附加 实现特殊情况。

标签: c# circular-dependency


【解决方案1】:

CountdownTimer 应该不知道 Controller。

Controller 应该实例化和引用 CountdownTimer 并使用它的方法并相应地输出,例如它应该订阅 timers Tick 事件处理程序,以正确的频率更新 UI。

看看Hollywood Principle,它使用了“不要打电话给我们,我们会打电话给你”的说法。将此句柄应用于您的场景,意味着 CountdownTimer 不应该“调用”控制器,控制器应该“调用”CountdownTimer。在此 Wikipedia 条目中,以下摘录完全适用于您正在做的事情:

使这成为可能的关键是牺牲控制元素。 系统运行您的程序,而不是您的程序运行系统 程序。在我们的示例中,我们的程序可以注册定时器事件, 并编写相应的事件处理程序来更新坐标。 该程序将包括其他回调以响应其他事件, 例如当系统需要重新绘制窗口的一部分时。这 系统应提供合适的上下文信息,以便处理程序可以 执行任务并返回。用户的程序不再包括 显式控制路径,除了初始化和注册。

UIProject 的唯一关注点应该是管理 UI。因此,它不应包含通用 CountdownTimer 类的实现。

【讨论】:

    猜你喜欢
    • 2013-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-06
    • 1970-01-01
    • 2018-06-02
    • 2014-07-27
    • 1970-01-01
    相关资源
    最近更新 更多