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


i use advice on refactoring. in application users able dynamically add new form fields; customfield. each type (text, dropdown, checkbox, etc.) viewmodel (textboxviewmodel, dropdownviewmodel, checkboxviewmodel, etc.) defined.

when post form, appropriate edit action executed , read each customfield store values.

currently implementation works ugly; switch/case/if/else through viewmodel types , based on type execute required logic.

this 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 textboxviewmodel)                 {                     attribute.value = ((textboxviewmodel) cvm).value;                 }else if (cvm dropdownlistviewmodel)                 {                     attribute.value = ((dropdownlistviewmodel)cvm).values;                 }                 ticket.attributes.add(attribute);             }         } 

and refactor this, without putting logic in viewmodel. best come visitor pattern add accept method viewmodel class, , use visitors execute logic required:

this still require same switching logic on types in addattribute method:

foreach (var cvm in model.controls)             {                 ticket.attributes.addattribute(cvm);             } 

this require logic in viewmodel class

foreach (var cvm in model.controls)             {                 ticket.attributes.add(cvm.addattribute);             } 

i want refactor create more generic approach, in future when new types of fields added don't have update codes new constructions check types.

[solution afer provided help]

i had cast object, cannot use different returntypes in different implementations of icontrolviewmodel 1 part have work around, overall beautiful.

  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         {             { return "textbox"; }         }         public override object outputvalue         {                         {                 return value;             }         }          public string value {set; }      } 

1) create interface defines have output value property on each of view models

public interface icontrolviewmodel {     object outputvalue{get;} } 

2) implement interface in each of viewmodels:

public textboxviewmodel: icontrolviewmodel {     ...     public object outputvalue     {                  {                //return whatever expected output value control             return value;          }     }     ... } 

3) can attributes single linq statement:

ticket.attributes = model.controls     .oftype<icontrolviewmodel>()     .select(cvm => new ticketattribute {         id = cvm.id,         name = cvm.name,         value = cvm.outputvalue         })     .tolist(); 

4) code work fine if create new control types, make sure implement interface in new viewmodels.


Comments

Popular posts from this blog

c - Bitwise operation with (signed) enum value -

xslt - Unnest parent nodes by child node -

YouTubePlayerFragment cannot be cast to android.support.v4.app.Fragment -