使用许多if和duplicated逻辑从不同的Controls类中提取值来重构代码的最佳方法是什么

Ser*_*hei 4 c# refactoring design-patterns

我在WPF应用程序中有以下代码

if (panel != null)
{
     IList listOfValues = new ComparableListOfObjects();
        var childControls = panel.GetChildren<Control>(x => x.Visibility == Visibility.Visible);
 foreach (Control childControl in childControls)
 {
    var textBox = childControl as TextBox;
    if (textBox != null)
    {
        listOfValues.Add(textBox.Text);
        continue;
    }

    var comboBox = childControl as ComboBox;
    if (comboBox != null)
    {
        listOfValues.Add(comboBox.SelectedItem);
        continue;
    }

    var datePicker = childControl as DatePicker;
    if (datePicker != null)
    {
        listOfValues.Add(datePicker.SelectedDate.GetValueOrDefault());
        continue;
    }
    var numericBox = childControl as NumericUpDown;
    if (numericBox != null)
    {
        listOfValues.Add(numericBox.Value);
        continue;
    }

}
Run Code Online (Sandbox Code Playgroud)

重构这个代码的最佳方法是什么,重复相同的逻辑,从不同的控件中提取值,如?

        var numericBox = childControl as NumericUpDown;
    if (numericBox != null)
    {
        listOfValues.Add(numericBox.Value);
        continue;
    }
Run Code Online (Sandbox Code Playgroud)

在其他方法的同一个类中,有相同的代码

        private static object GetControlValue(Control control)
    {
        if (control == null)
            throw new ArgumentNullException("control");

        var textBox = control as TextBox;
        if (textBox != null)
            return textBox.Text;

        var comboBox = control as ComboBox;
        if (comboBox != null)
            return comboBox.SelectedValue;

        var datePicker = control as DatePicker;
        if (datePicker != null)
            return datePicker.SelectedDate.GetValueOrDefault();

        var numericUpDown = control as NumericUpDown;
        if (numericUpDown != null)
            return numericUpDown.Value;

        throw new NotSupportedException();
    }
Run Code Online (Sandbox Code Playgroud)

我应该使用策略设计模式,但在这种情况下,我需要为每种类型的控件创建额外的类?

你能建议我更好地适应这个问题吗?提前致谢.

Ant*_*ram 6

拥有ifswitch陈述并不是一件坏事.即使进行一些基本类型检查也不一定是坏事,特别是当使用的类型不能以多态方式使用时.这种逻辑表达不止一次是不赞成的,因为你正在重复自己,并且你有相同变化的多个维护点.

在您的原始代码段中,您可以执行此操作

var blah = obj as Foo;
if (blah != null)
{
    someList.Add(blah.Value); 
}
Run Code Online (Sandbox Code Playgroud)

并针对其他几种控件类型重复此操作.但是后来在你的私有方法中,你基本上有相同的逻辑表示相同的次数.

var blah = obj as Foo;
if (blah != null)
    return blah.Value;
Run Code Online (Sandbox Code Playgroud)

唯一的区别是,在第一个代码段中,您获取值并将其添加到列表中.在第二个中,您返回值.第一个片段应该取消其类型检查逻辑,它应该使用已经在另一个方法中表达的逻辑.

foreach (var control in childControls)
{
    listOfValues.Add(GetControlValue(control));
}
Run Code Online (Sandbox Code Playgroud)

这个想法是不要重复自己.干.