lundi 3 août 2015

switch/case on viewmodel in controller, refactoring advice highly appreciated

I could use some advice on refactoring. In my application users are able to dynamically add new form fields; customfield. For each type (text, dropdown, checkbox, etc.) a ViewModel (TextBoxViewModel, DropDownViewModel, CheckboxViewModel, etc.) is defined.

When I post a form, the appropriate Edit action is executed and I read each customfield to store their values.

Currently the implementation works but is ugly; I switch/case/if/else through all ViewModel types and based on the type I execute the required logic.

This is the the current implementation:

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);
            }
        }

And I would like to refactor this to something like this, but without putting all logic in the ViewModel. Best I could come up with is the visitor pattern where I would add a Accept method to the ViewModel class, and use visitors to execute the logic required:

This would still require the same switching logic on types in the AddAttribute method:

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

This would require logic in the ViewModel class

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

I want to refactor this to create a more generic approach, so that in future when new types of fields are added I don't have to update all codes with new constructions to check for types.

Aucun commentaire:

Enregistrer un commentaire