c# - How to seperate commands out of big viewmodel -


my viewmodel contains lots of commands, makes viewmodel big. want seperate command out of viewmodel. currently, soluton create class each command below,

 public class testcommand : commandbase {     private mainviewmodel vm;      public testcommand(mainviewmodel vm)     {         this.vm = vm;     }      public override bool canexecute(object parameter)     {         return true;     }      public override void executecommand(object parameter)     {         vm.logger.log(...);         ...     } } 

since need use method or properties in viewmodel, have pass viewmodel parameter command. solution, there're 2 disadvantages: 1. there're lots of command files in project, if average count of command in 1 view 15, 10 views have 150 command files in project; 2. passing viewmodel parameter command needs properties or methods should private have been change public; it's strange pass viewmodel command.

is there other solution seperate commands?

tl;dr:

viewmodels presentation logic expressed in commands, it's not unusual commands take big chunk of viewmodel's code. don't try hard make viewmodels plain data holders (like common in asp.net mvc when using viewmodels) inotifypropertychanged.

long version

with lack of more details it's hard give concrete tips, here general guidelines. may update question more details kind of commands using , i'll try update question.

  1. presentation logic

    main concern of viewmodels presentation. there no place business logic in viewmodels.

    business logic has extracted either business/domain models (if follow rich domain model) or services (in anemic domain model). in rich domain model service layers quite thin , there coordinate actions between multiple models.

    so if viewmodel/commands doing kind of logic not related presentation (if click button a, disable buttons b, c , d or hide groupboxa or "disable button if data missing (canexecute of icommand)) it's doing much.

  2. separation of concerns:

    it may possible viewmodel tries more it's intended do. logger in example such hint. logging not viewmodel concern.

    viewmodel presentation , presentation logic , logging application concern (as not belong domain/business logic).

    often viewmodel can split 2 or more viewmodels (i.e. viewmodel manages list of customers , allow edit selected customer, can split 2 or 3 viewmodels: customersviewmodel (display list), customerdetailviewmodel or customerviewmodel (detail customer) , customereditviewmodel (to edit customer in question)

    concerns logging , caching should done using i.e. decorator pattern. requires services and/or repositories use , implement interfaces, can create decorators caching or logging , rather inject original instance of service, implement decorator.

    dependency injection (di) , inversion of control (ioc) containers this. having manually wire (aka poor mans di) pain in butt. concrete examples out of scope of answer.

  3. business logic in commands

    commands shouldn't contain business logic. when commands contain code (usually more 5-20 lines of code) clue, commands may much.

    commands should wire multiple calls services , assign data properties and/or rise events/messages (that relevant presentation layer. not confused domain events, shouldn't raised inside commands). similar "actions" in mvc (like used frameworks in asp.net mvc example).

    commands should this

    var customer = new customer { name = this.customername, mail = this.customermail }; try {     this.customerservice.addcustomer(customer);     // add observable<customer> list ui gets updated     this.customers.add(customer);     // service should have populated id field of customer when persisting     // notify other viewmodels new customer has been added     this.messagebus.publish(new customercreated() { customerid = customer.id } ); } catch (somespecificexception e) { // handle exception }  

    or

    this.customers = this.customerrepository.getall(); // or async commands this.customers = await this.customerrepository.getallasync(); 
  4. encapsulation

    many commands tightly coupled viewmodel , need access internal state of the viewmodel or model (the model shouldn't directly exposed view, couples model view , change in model breaks view , bindings).

    moving these icommands out viewmodels may difficult without breaking encapsulation.

of course can implement multiple commands in 1 class

public class myviewmodelcommandhandler {     private readonly imyrepository myrepository;      public myviewmodelcommandhandler(/* pass dependencies here*/)     {         // assign , guard dependencies          mycommand = new relaycommand(mycommand, canexecutemycommand);         myothercommand = new relaycommand(myothercommand, canexecutemyothercommand);     }      public icommand mycommand { get; protected set; }      public icommand myothercommand { get; protected set; }       private void mycommand()      {         //     }      private void canexecutemycommand()      {         // validate     }      private void myothercommand()      {         // else     }      private void canexecutemyothercommand()      {         // validate     } } 

and in viewmodel assign these commands

public class myviewmodel : viewmodelbase  {     public myviewmodel()     {         var commandhandler = new mycommandhandler(this);         onecommand = commandhandler.mycommand;         othercommand = commandhandler.myothercommand;     }      public icommand onecommand { get; private set; }      public icommand othercommand { get; private set; }  } 

you can inject mycommandhandler view using ioc container, require remodeling command handler class bit, create icommand on demand. may use

public class myviewmodel : viewmodelbase  {     public myviewmodel(mycommandhandler commandhandler)     {         onecommand = commandhandler.createmycommand(this);         othercommand = commandhandler.createmyothercommand(this);     }      public icommand onecommand { get; private set; }      public icommand othercommand { get; private set; }  } 

but shifts problem, won't solve points 1. 5. though. i'd suggest try suggestions aboves list first , if commands still contain "too many lines of code", try other solution.

i don't creates unnecessary abstractions little gain.

it's not uncommon viewmodels consist of presentation logic, that's purpose , presentation logic typically inside commands. except that, have properties , constructor. properties shouldn't have else other checking if value changed, assign , 1 or more onpropertychanged calls.

so 50-80% of viewmodel code commands.


Comments

Popular posts from this blog

php - Wordpress website dashboard page or post editor content is not showing but front end data is showing properly -

How to get the ip address of VM and use it to configure SSH connection dynamically in Ansible -

javascript - Get parameter of GET request -