控制器中viewmodel的Switch /case,任何重构建议

本文关键字:任何重 构建 case viewmodel Switch 控制器 | 更新日期: 2023-09-27 18:05:58

我需要一些关于重构的建议。在我的应用程序中,用户能够动态添加新的表单字段;customfield。对于每种类型(文本,下拉框,复选框等)都定义了一个ViewModel (TextBoxViewModel, DropDownViewModel, CheckboxViewModel等)。

当我发布一个表单时,将执行适当的Edit操作,并读取每个自定义字段以存储它们的值。

目前的实现工作,但是丑陋的;我在所有ViewModel类型之间切换/case/if/else,并根据类型执行所需的逻辑。

这是当前的实现:

private static void MapToModel(Ticket ticket, TicketViewModel model)
    {
        ticket.Id = model.Id;
        ticket.Name = model.Name;
        ticket.Attributes.Clear();
        foreach (var cvm in model.Controls)
        {
            var attribute = new TicketAttribute
            {
                Id = cvm.Id,
                Name = cvm.Name,
            };
            if (cvm is TextBoxViewModel)
            {
                attribute.Value = ((TextBoxViewModel) cvm).Value;
            }else if (cvm is DropDownListViewModel)
            {
                attribute.Value = ((DropDownListViewModel)cvm).Values;
            }
            ticket.Attributes.Add(attribute);
        }
    }

我想把它重构成这样的东西,但不把所有的逻辑放在ViewModel中。我能想到的最好的方法是访问者模式,我将向ViewModel类添加一个Accept方法,并使用访问者来执行所需的逻辑:

这仍然需要在AddAttribute方法中的类型上使用相同的切换逻辑:

foreach (var cvm in model.Controls)
    {
        ticket.Attributes.AddAttribute(cvm);
    }

这需要ViewModel类中的逻辑

foreach (var cvm in model.Controls)
    {
        ticket.Attributes.Add(cvm.AddAttribute);
    }

我想重构它来创建一个更通用的方法,这样在将来添加新类型的字段时,我就不必用新的结构来更新所有的代码来检查类型。

[提供帮助后的解决方案]

我必须转换对象,我不能在IControlViewModel的不同实现中使用不同的返回类型,所以这是我必须解决的一部分,但总的来说这是美丽的。

  ticket.Attributes = model.Controls
    .OfType<IControlViewModel>()
    .Select(cvm => new TicketAttribute {
        Id = cvm.Id,
        Name = cvm.Name,
        Value = (string)cvm.OutputValue
        })
    .ToList();

  public interface IControlViewModel
    {
        string Id { get; }
        string Name { get; }
        object OutputValue { get; }
    }
    public abstract class ControlViewModel : IControlViewModel
    {
        public string Id { get; set; }
        public abstract string Type { get; }
        public string Label { get; set; }
        public string Name { get; set; }
        public bool Visible { get; set; }
        public abstract object OutputValue { get; }
    }
    public class TextBoxViewModel : ControlViewModel
    {
        public override string Type
        {
            get { return "textbox"; }
        }
        public override object OutputValue
        {
            get
            {
                return Value;
            }
        }
        public string Value {set; }
     }

控制器中viewmodel的Switch /case,任何重构建议

1)创建一个接口,定义每个视图模型的输出值属性

public interface IControlViewModel
{
    object OutputValue{get;}
}

2)在每个视图模型中实现接口:

public TextBoxViewModel: IControlViewModel
{
    ...
    public object OutputValue
    {
        get 
        {   
            //return whatever is your expected output value from control
            return Value; 
        }
    }
    ...
}

3)然后,您可以使用这条LINQ语句获得所有属性:

ticket.Attributes = model.Controls
    .OfType<IControlViewModel>()
    .Select(cvm => new TicketAttribute {
        Id = cvm.Id,
        Name = cvm.Name,
        Value = cvm.OutputValue
        })
    .ToList();
4)即使你创建了新的控件类型,这段代码也能很好地工作,只是要确保在你的新视图模型中实现接口。
相关文章: