【问题标题】:Principle DRY in validation?验证中的原则 DRY?
【发布时间】:2017-07-11 19:43:58
【问题描述】:

我使用工具箱菜单中的标准 DataGridView。

我通过事件cellEditEnd 验证DataGridView 中的每个单元格。它看起来像这样:

private void dataGrid_CellEditEnding(object sender,DataGridCellEditEndingEventArgs e)
{
     // Below I demonstrate pseudo code for brevity

     if(cell.name.value is not Number){
         print "Wrong cell value";
     }
}

因此,在另一种形式 (WinForms) 中,我具有从 Excel 文件导入数据并将其显示在 DataGridView 中的功能。

我需要在插入每个单元格之前验证 Excel 数据。为此,我可以使用事件CellValidation。但我不想重复我在dataGrid_CellEditEnding 方法中使用的相同代码。

如何避免重复代码?

【问题讨论】:

  • 是否有理由不将验证代码放入单独的函数中,并在编辑和从 excel 导入时调用它?

标签: c# oop dry


【解决方案1】:

你可以看看责任链设计模式,你的代码将是可配置的并且更面向对象,看起来像这样:

    public interface IHandler
    {
        void Handle(string value);
    }

    public abstract class CellRequestTemplate : IHandler
    {
        protected readonly IHandler _next;
        protected CellRequestTemplate(IHandler next)
        {
            _next = next ?? throw new ArgumentNullException(nameof(next));
        }

        public abstract void Handle(string value);
    }

    public sealed class FirtsRuleForCell : CellRequestTemplate
    {
        public FirtsRuleForCell(IHandler next) : base(value, next) { }
        public override void Handle(string value)
        {
            if(value is number)
            {
                _next.Handle(value);
            }
            else
            {
                //print "Wrong cell value";
            }
        }
    }

    public sealed class SecondRuleForCell : CellRequestTemplate
    {
        public SecondRuleForCell(IHandler next) : base(value, next) { }
        public override void Handle(string value)
        {
            //if some validation
            //do something
            //else 
            //
            _next.Handle(value);

        }
    }

    public sealed class EndOfChain : IHandler
    {
        public void Handle(string value)
        {
            throw new InvalidOperationException("End of Chaing, cant handle");
        }
    }

    public interface IHandleCellFactory
    {
        IHandler CreateHandler();
    }

    public sealed class Form1GridHandler : IHandleCellFactory
    {
        public IHandler CreateHandler()
        {
            return new FirtsRuleForCell(new SecondRuleForCell(new EndOfChain()));
        }
    }

    public sealed class Form2GridHandler : IHandleCellFactory
    {
        public IHandler CreateHandler()
        {
            return new SecondRuleForCell(new EndOfChain());
        }
    }


    public abstract class ClientCode
    {
        private void dataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
        {
            // Below I demonstrate pseudo code for brevity
            var valueToHandle = string.Empty; //cell.name.value;
            var handler = new Form1GridHandler().CreateHandler();
            handler.Handle(valueToHandle);
            //continue with Execution code
        }
    }

有关设计模式的更多信息,look at this link as reference。 希望这会有所帮助,问候!

【讨论】:

    【解决方案2】:

    如何创建一个静态的ValidationHelper 类,其中包含所有验证方法,然后在需要时调用它们。

    public static class ValidationHelper
    {
      public static void ValidateIsNumeric(string value)
      {
        if(value is not Number){
          print "Wrong cell value";
        }
      }
    }
    

    然后你可以调用:

    private void dataGrid_CellEditEnding(object sender,DataGridCellEditEndingEventArgs e)
    {
       ValidationHelper.ValidateIsNumeric(cell.name.value);
    }
    

    【讨论】:

    • 很好,但是如何知道我需要验证什么单元格以及如何验证?
    • 恐怕你仍然需要知道每个单元格应该是什么数据类型,然后为每个单元格写一行以将其传递给正确的验证器方法(字符串、日期、数字等)。这只是防止您复制验证代码本身。
    • @OlegP 如果您认为这回答了您的(原始)问题,请投票或标记为已回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-15
    • 2015-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多