Tasks interaction
The source code of this example can be found under "Examples\TasksInteraction\" subfolder
of the MVC# root folder.
Introduction
Application logic
Main Task
Employees Controller
Award Bonus Task
Award Bonus Main Controller
Advanced Options Controller
Presentation
Conclusion
Introduction
In our first example
we have concerned an execution of a single task and have discussed interaction between
task's views, its controllers and the task object itself. But one important question
left uncovered is how two or more tasks interact with each other. This article considers
an example of communication between tasks in MVC# Framework.
Application logic
The example we concern here deals with a list of employees and allows to award
a bonus to each employee. Bonus awarding procedure requires entering several options
which determine the resulting bonus sum.
We will construct the application of two tasks: one for browsing through the list
of employees (main task), the other for awarding a bonus to a particular employee
(bonus award task).
Main Task
Main task will include a single view showing a list of employees, which will be
activated on the task start:
public class MainTask : TaskBase
{
[IPoint(typeof(EmployeesController))]
public
const string Employees = "Employees";
public override void OnStart(object param)
{
Navigator.NavigateDirectly(Employees);
}
}
Besides a list of employees the employees view will contain a button (or menu item
or whatever else) for starting a bonus award task. However the employees view will
not start this task itself. Instead, according to the MVP pattern, this work should
be delegated to the associated EmployeesController instance.
Employees Controller
As decided above the Employees controller class should contain a method (say, AwardBonus())
for starting a bonus award task. For this task to execute, it needs to know the
employee to be awarded. That is why we pass the current employee object to the task
starting procedure:
public class EmployeesController : ControllerBase
{
public void AwardBounus()
{
Employee currEmpl = (View as IEmployeesView).CurrentEmployee;
Task.TasksManager.StartTask(typeof(AwardBonusTask), currEmpl);
}
}
After finishing its execution the bonus award task should return control to the main task.
Thus a reference to the main task should also be passed to the bonus award task:
public class EmployeesController : ControllerBase
...
public void AwardBounus()
{
Employee currEmpl = (View as IEmployeesView).CurrentEmployee;
Task.TasksManager.StartTask(typeof(AwardBonusTask),
new object[] { currEmpl, Task });
}
Next, we will discuss the AwardBonusTask class and corresponding controller classes.
Award Bonus Task
The bonus award task will have two views. The main view will have edit boxes to
choose some basic options and an "OK" button to award a bonus and return to the
main task. The second view will be used for entering advanced options:
public class AwardBonusTask : TaskBase
{
[IPoint(typeof(ABMainController), AdvancedOptionsView)]
public const string MainView = "Main View";
[IPoint(typeof(ABAdvancedOptionsController), MainView)]
public const string AdvancedOptionsView = "Advanced Options View";
}
When started, the bonus award task receives the employee to be awarded and the originating
task as input parameters. These parameters are then stored in the task's public
fields. After that the main view gets activated:
public class AwardBonusTask : TaskBase
...
public Employee Employee;
public ITask OriginatingTask;
public override void OnStart(object param)
{
Employee = (param as object[])[0] as Employee;
OriginatingTask= (param as object[])[1] as ITask;
Navigator.NavigateDirectly(MainView);
}
Award Bonus Main Controller
In the bonus award main view when a user decides to award a bonus and clicks
"OK" the control should be passed to the ABMainController.DoAwardBonus() method.
This method calculates the bonus sum, assigns it to the employee and returns control
back to the main task:
public class ABMainController : ControllerBase
{
public void DoAwardBonus()
{
int contractsMade = (View as IABMainView).ContractsMade;
int customersAttracted = (View as IABMainView).CustomersAttracted;
decimal baseSalary = (Task as AwardBonusTask).Employee.BaseSalary;
decimal workerOfTheMonthBonus =
(Task as AwardBonusTask).IsWorkerOfTheMonth ? baseSalary * .10m : 0;
decimal specialServicesBonus =
(Task as AwardBonusTask).SpecialServices ? baseSalary * .5m : 0;
(Task as AwardBonusTask).Employee.SetBonusSum(contractsMade * 15000m +
customersAttracted * 15000m + workerOfTheMonthBonus +
specialServicesBonus);
(Task as AwardBonusTask).OriginatingTask.OnStart(null);
}
}
Here we do not need to pass anything back to the main task. In more complicated
situations, however, the originating task's behavior might depend on parameters
passed back to it by nested tasks.
A few changes should also be made to the MainTask class. The point is that Navigator.NavigateDirectly(...)
would not activate a view if it is already marked as current for the task. That
is why calling MainTask.OnStart(...) will have no effect if returning back to the
main task. Instead, we should use Navigator.ActivateView(...), it will activate
a view even if it is current for the task.
public class MainTask : TaskBase
...
public override void OnStart(object param)
{
Navigator.NavigateDirectly(Employees);
Navigator.ActivateView(Employees);
}
As we can see tasks communication is done by simply invoking task start methods
with necessary parameters. For existing task instances we use Task.OnStart(...)
method, for new tasks TasksManager.StartTask(...) is used.
Advanced Options Controller
This controller simply saves options entered in the advanced options view to the
task's public fields, and then navigates back to the main award bonus view:
public class ABAdvancedOptionsController : ControllerBase
{
public void DoEnterOptions()
{
(Task as AwardBonusTask).IsWorkerOfTheMonth = (View as
IABAdvancedOptionsView).IsWorkerOfTheMonth;
(Task as AwardBonusTask).SpecialServices = (View as
IABAdvancedOptionsView).SpecialServices;
Task.Navigator.Navigate(AwardBonusTask.MainView);
}
}
Presentation
Steps to create views are very similar to those discussed in our
first example, so we will omit them here.
Conclusion
Tasks interaction in MVC# is no harder than an ordinary interaction between two
objects: one tasks just passes needed data to the other task's OnStart(...) method
(either directly or by calling TasksManager.StartTask(...) if the task instance
does not exist yet).
The source code of this example can be found under "Examples\TasksInteraction\" subfolder
of the MVC# root folder.