我如何最好地重构这个C#代码?

我想重构以下代码,如何注入通知处理程序?最小的原始代码更改和必要时的最佳重构.

public class TestEventHandlers
{
    public TestEventHandlers() { }

    public void OpenMarket(Page page)
    {
        var Id = page.Request["MarketId"];

        var repository = new EntityRepository();
        IEntity market = repository.GetById(Id);

        if (market.State != "Open")
        {
            throw new Exception("The market is not open!");
        }
        else
        {
            market.Open();

            repository.SaveChangesTo(market);

            var smtpClient = new SmtpClient();

            var message = new MailMessage();
            message.Subject = "market open";
            message.Body = market.ToString() + " was open.";
            message.To.Add(new MailAddress("market@mail.com"));

            smtpClient.Send(message);
        }
    }

    public void CloseMarket(Page page)
    {
        var Id = page.Request["MarketId"];
        var repository = new EntityRepository();
        IEntity market = repository.GetById(Id);

        if (market.State == "Close")
        {
            throw new Exception("The market is already close!");
        }
        else
        {
            market.Close();

            repository.SaveChangesTo(market);

            var smtpClient = new SmtpClient();

            var message = new MailMessage();
            message.Subject = "market closed";
            message.Body = market.ToString() + " has been closed.";
            message.To.Add(new MailAddress("market@mail.com"));

            smtpClient.Send(message);
        }
    }
}

我已经像下面那样重构了它 –

public class TestEventHandlers
{
        public TestEventHandlers() { }

        public void OpenMarket(Page page)
        {
            var Id = page.Request["MarketId"];
            if (id!=null)
            { 
            var repository = new EntityRepository();
            IEntity market = repository.GetById(Id);

            if (market.State != "Open")
            {
                throw new Exception("The market is not open!");
            }
            else
            {
                market.Open();

                repository.SaveChangesTo(market);

                SendEmailNotification("market open", market.ToString() + " was open.", "market@mail.com");
            }
           }
          else
            {
                throw new Exception("Id can not be null");
            }
        }

        private static void SendEmailNotification(string subject,string body,string emailAddress)
        {
            var smtpClient = new SmtpClient();

            var message = new MailMessage();

            message.Subject = subject;
            message.Body = body;
            message.To.Add(new MailAddress(emailAddress));

            smtpClient.Send(message);
        }

        public void CloseMarket(Page page)
        {
            var Id = page.Request["MarketId"];
            if(id!=null)
            {
            var repository = new EntityRepository();
            IEntity market = repository.GetById(Id);

            if (market.State == "Close")
            {
                throw new Exception("The market is already close!");
            }
            else
            {
                market.Close();

                repository.SaveChangesTo(market);

                SendEmailNotification("market closed", market.ToString() + " has been closed.", "market@mail.com");
            }
        }
           else
            {
                throw new Exception("Id can not be null");
            }
       }
    }

最佳答案 我会用这样的东西:

public interface INotifier
{
    void SendEmailNotification(string subject, string body, string emailAddress);
}

public class Notifier : INotifier
{
    public void SendEmailNotification(string subject,string body,string emailAddress)
    {
        var smtpClient = new SmtpClient();

        var message = new MailMessage();

        message.Subject = subject;
        message.Body = body;
        message.To.Add(new MailAddress(emailAddress));

        smtpClient.Send(message);
    }
}

public class TestEventHandlers
{       
    public INotifier Notifier { get; set; }

    public TestEventHandlers()
    {           
        Notifier = new Notifier();
    }

    public void OpenMarket(Page page)
    {
        var Id = page.Request["MarketId"];
        if (id!=null)
        { 
            var repository = new EntityRepository();
            IEntity market = repository.GetById(Id);

            if (market.State != "Open")
            {
                throw new Exception("The market is not open!");
            }
            else
            {
                market.Open();

                repository.SaveChangesTo(market);

                Notifier.SendEmailNotification("market open", market.ToString() + " was open.", "market@mail.com");
            }
        }
        else
        {
            throw new Exception("entityId can not be null");
        }           
    }

    public void CloseMarket(Page page)
    {
        var Id = page.Request["MarketId"];
        if(id!=null)
        {
            var repository = new EntityRepository();
            IEntity market = repository.GetById(Id);

            if (market.State == "Close")
            {
                throw new Exception("The market is already close!");
            }
            else
            {
                market.Close();
                repository.SaveChangesTo(market);
                Notifier.SendEmailNotification("market closed", market.ToString() + " has been closed.", "market@mail.com");
            }
        }
        else
        {
            throw new Exception("entityId can not be null");
        }
    }       
}

在这种情况下,您的INotifier默认为构造函数的常规实现,但在需要时可以使用访问器覆盖.如果您希望在不进行测试时始终注入依赖项,则只需向构造函数添加参数即可.

希望这可以帮助.

点赞