Related to this other question: How to inject an action into a command using Ninject?
Based on the comments on the above-referenced question, I take it that I would just need to create some command classes and inject them in my view model so that the view's controls just need to bind to them. I conceptually agree and understand the benefits. Besides, I wish to be as clean as possible using Ninject, DI and Constructor Injection.
Following these important rules, here's what I've come with so far.
CreateCategoryCommand
public class CreateCategoryCommand : ICommand {
public CreateCategoryCommand(CreateCategoryView view) {
if(view == null) throw new ArgumentNullException("view");
this.view = view;
}
public bool CanExecute(object parameter) { return true; }
public event EventHandler CanExecuteChanged;
public void Execute(object parameter) { view.Show(); }
private readonly CreateCategoryView view;
}
CategoriesManagementViewModel
public class CategoriesManagementViewModel {
public CategoriesManagementViewModel(ICommand createCommand) {
if (createCommand == null) throw new ArgumentNullException("createCommand");
this.createCommand = createCommand;
}
public ICommand CreateCommand { get { return createCommand; } }
private readonly ICommand createCommand;
}
So now when the CategoriesManagementView is initialized, it is constructor-injected with the CategoriesManagementViewModel, which in turn is constructor-injected with the CreateCategoryCommand, which in turn is constructor-injected with the CreateCategoryView, so no redundant dependency, neither any cycle-dependency.
Now, when I the CategoriesManagementView.CreateButton, it shall trigger the bound CategoriesManagementViewModel.CreateCommand, which will show the CreateCategoryView to the user, and this view shall have its own proper commands as well injected the same way.
Finally, this would render the RelayCommand class as useless...
Is that it?
First, I agree that RelayCommand and DelegateCommand and the like are ways of implementing commands that violate SOLID principles, so your solution here to replace them with a separate class is the correct one. Doing so also keeps your ViewModels much cleaner.
That said, you're violating MVVM pretty badly by having a class in your ViewModels layer (the CreateCategoryCommand) have knowledge of a concrete that is in your Views layer (CreateCategoryView). Nothing in your ViewModels layer should have a direct reference to anything in your Views layer.
Imagine it this way - you've separated your layers out into different dlls - Views.dll, ViewModels.dll, Models.dll, DataLayer.dll. If something in your ViewModels has a reference to a concrete in your Views, and obviously your Views will have a reference to ViewModels (as is necessary), then you have a circular reference problem.
The solution is to have your View object implement an interface (Interface Segregation Principle) like IDialog or IUiDisplay (choose the name depending on how abstract you want to be), and have your command have a dependency on that interface, NOT the direct concrete type, like so:
In Views:
public class CreateCategoryView : ..., IUiDisplay
{
...
}
In ViewModels:
public interface IUiDisplay
{
void Show();
}
public class CreateCategoryCommand : ICommand
{
public CreateCategoryCommand(IUiDisplay uiDisplay) {
if(display == null) throw new ArgumentNullException("uiDisplay");
this.display = uiDisplay;
}
private readonly IUiDisplay display;
...
}
Now, your Command no longer has a direct dependency on a concrete (so it is now mockable and testable!) from a higher layer. Now you can have your DI/IOC resolve the command dependency to the specific view class you want to inject. (I'd personally inject a view factory into the command instead, and only create the view lazily, but that's a different discussion).
One related note - if you implement commands by directly having them implement ICommand, then you're going to repeat yourself a lot (DRY). My suggestion is to create an abstract base class (CommandBase or something) that implements the requirements of ICommand. You'll find that all your commands that derive from it will only override Execute() and sometimes CanExecute(). This saves you from having to implement the event (and code to raise the event) in every command, and in many cases saves you from having to implement CanExecute since most commands just return true.
Related
Trying to use Command/Handler pattern and Aspect Oriented Programming with Simple Injector.
I have my command and handler classes.
ICommandHandler.cs
public interface ICommandHandler<TCommand>
{
void Handle(TCommand command);
}
MakeCoffeeCommand.cs
public class MakeCoffeeCommand
{
public string Flavor { get; set; }
}
MakeCoffeeCommandHandler.cs
internal class MakeCoffeeCommandHandler : ICommandHandler<MakeCofeeCommand>
{
public void Handle(MakeCoffeeCommand command)
{
...
}
}
MakeCakeCommand.cs
public class MakeCakeCommand
{
public float OvenTemperature { get; set; }
}
MakeCakeCommandHandler.cs
internal class MakeCakeCommandHandler : ICommandHandler<MakeCakeCommand>
{
public void Handle(MakeCakeCommand command)
{
...
}
}
So far, I can inject implementation through this single rule.
//this rule automagically ignores possibly existing decorators! :-)
c.Register(typeof(ICommandHandler<>), typeof(ICommandHandler<>).Assembly);
Then, I would like to register decorators aimed at validating the command instance. My decorator implementations depend on the concrete command types. I created an interface all the decorators have to inherit from.
ICommandHandlerValidator.cs
public interface ICommandHandlerValidator<TCommand> : ICommandHandler<TCommand>
{
}
Then, the concrete decorators.
ValidatorMakeCoffeeCommandDecorator.cs
internal class ValidatorMakeCoffeeCommandDecorator
: ICommandHandlerValidator<MakeCoffeeCommand>
{
private readonly ICommandHandler<MakeCoffeeCommand> decoratee;
public ValidatorMakeCoffeeCommandDecorator(ICommandHandler<MakeCoffeeCommand> decoratee)
{
this.decoratee = decoratee;
}
public void Handle(MakeCoffeeCommand command)
{
...
}
}
ValidatorMakeCakeCommandDecorator.cs
internal class ValidatorMakeCakeCommandDecorator
: ICommandHandlerValidator<MakeCakeCommand>
{
private readonly ICommandHandler<MakeCakeCommand> decoratee;
public ValidatorMakeCakeCommandDecorator(ICommandHandler<MakeCakeCommand> decoratee)
{
this.decoratee = decoratee;
}
public void Handle(MakeCakeCommand command)
{
...
}
}
I'm trying to register these validators with a single line, as in the previous case.
c.RegisterDecorator(typeof(ICommandHandler<>), typeof(ICommandHandlerValidator<>));
But I get this error.
The given type ICommandHandlerValidator<TCommand> is not a concrete type. Please use one of the other overloads to register this type.
It this a correct approach?
If yes, how is it possible to get rid of the error?
Note: I have to implement multiple decorators for all cross-cutting concerns. Some of them depend on the concrete command (i.e. authorization, full-text indexing), some do not, and have the same implementation shared by all the commands (i.e. logging, performance analysis).
It this a correct approach?
This answer might be a bit opinionated, but to me, this isn't the right approach. Your ICommandHandlerValidator<T> interface serves no function, and your decorators can as easily derive directly from ICommandHandler<T>.
On top of that, you are somewhat 'abusing' decorators to implement very specific logic, while decorators are best suited to implement very generic cross-cutting concerns.
Although you might argue that validation is very generic, your implementations aren't generic at all, since each decorator has logic that is specific to a single handler implementation. This leads to the situation that you get many decorators, and need to batch-register them.
What I typically like to do is to take a step back and look at the design. In your architecture you determined that business logic that mutates state is a certain artifact that deserves its own abstraction. You call this abstraction ICommandHandler<T>. Not only does this allow you to clearly distinguish these particular type of components from other components in the system, it allows you to batch register them and apply cross-cutting concerns very effectively.
While looking at your code, however, it seems to me that logic that validates commands before they are executed by their command handler has importance of its own in your application. That means it deserves an abstraction of its own. For instance, you can call it ICommandValidator<T>:
public interface ICommandValidator<TCommand>
{
IEnumerable<ValidationResult> Validate(TCommand command);
}
Note that this interface has no relationship with ICommandHandler<TCommand>. Validation components are a different artifact. The ICommandValidator<T> interface returns validation results, which can be practical for implementations. You might want to play with the best design for this validator.
Using this interface you can now define specific validators:
public class MakeCoffeeValidator : ICommandValidator<MakeCoffeeCommand> { ... }
public class MakeCakeValidator : ICommandValidator<MakeCakeCommand> { ... }
Besides the visibility of these validators in your design, this separate interface allows your validators to be batch-registered:
c.Collection.Register(typeof(ICommandValidator<>),
typeof(MakeCakeValidator).Assembly);
Here, the validators are registered as collection, assuming that there might be zero or multiple validator implementations for a single command. If there is always exactly one implementation (as you'll see with command handler implementations), you should call c.Register instead.
This by itself, however, doesn't do much, because those validators will not get executed by themselves. For this you will need to write a generic piece of cross-cutting code that can be applied to all command handlers in the system. In other words, you need to write a decorator:
public class ValidatingCommandHandlerDecorator<T> : ICommandHandler<T>
{
private readonly ICommandHandler<T> decoratee;
private readonly IEnumerable<ICommandValidator<T>> validators;
public ValidatingCommandHandlerDecorator(
IEnumerable<ICommandValidator<T>> validators,
ICommandHandler<T> decoratee)
{
this.validators = validators;
this.decoratee = decoratee;
}
public void Handle(T command)
{
var validationResults = (
from validator in this.validators
from result in validator.Validate(command)
select result)
.ToArray();
if (validationResults.Any())
{
throw new ValidationException(validationResults);
}
this.decoratee.Handle(command);
}
}
This decorator can be registered in a way you are already familair with:
c.RegisterDecorator(
typeof(ICommandHandler<>),
typeof(ValidatingCommandHandlerDecorator<>));
Although you could try to batch-register this decorator, together with all decorators in the system, that would typically not work out great. This is because the order in which you execute cross-cutting concerns is of vital importance. For instance, when you implement a deadlock retry decorator and a transaction decorator, you wish to have the deadlock decorator to wrap the transaction decorator, otherwise you might end up retrying a deadlocked operation outside the context of a transaction (because of the way SqlTransaction and SQL server work). Likewise, you wish to operate writing the audit trail inside a transaction. Otherwise you could end up missing an audit trail for a succeeded operation.
I know that in MVVM pattern (or possibly in any design pattern of this kind) we should keep our layers decoupled. From my understanding it also means, that I should keep my ViewModels separate. I'm having a bit trouble following this rule.
Say - I have a ConversationViewModel and a MessageViewModel - the former needs to create instances of the later. When ConversationViewModel gets notification about incoming message it spawns a new MessageViewModel instance and fills it with data.
The question is - if I create new MessageViewModel instances explicitly in the ConversationViewModel won't it make my app a bit harder to test? I mean - one unit of code is the ConversationViewModel and other is the MessageViewModel - I'd like to test both separate, so when somebody breaks something in the later, test for the former won't be affected. How do I achieve it?
I'm using MVVMLight, so I thought I would register MessageViewModel as an implementation of some interface, and then create a class like MockMessageViewModel implementing the same interface, but used only in tests. Then in the ConversationViewModel I'd ask the IOC container to just give me the registered implementation. Is it a good approach, or am I overreacting? Example code:
public class ViewModelLocator {
public ViewModelLocator() {
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (//in test) {
SimpleIoc.Default.Register<IMessageViewModel, MockMessageViewModel>();
}
else {
SimpleIoc.Default.Register<IMessageViewModel, MessageViewModel>();
}
}
public class ConversationViewModel : ViewModelBase {
public void MessageReceived(string data) {
//I'm thinking about doing this:
var vm = SimpleIoc.Default.GetInstance<IMessageViewModel>();
// instead of doing this
var vm = new MessageViewModel();
//do stuff with vm
}
}
Whether to use interface bases approach to separate the view models from each other is the design decision based on complexity of your application.
If you want to dynamically create instance of IMessageViewModel inside IConvesationViewModel; I would recommend instead of referring to IoC container in your ViewModel class inject a factory for creating IMessageViewModel in the ConversationViewModel constructor. Later you can use this factory to create instances of IMessageViewModel. A simple implementation of factory could be Func delegate.
public class ConversationViewModel
{
private Func<IMessageViewModel> _messageViewModelFactory;
public ConversationViewModel(Func<IMessageViewModel> messageViewModelFactory)
{
_messageViewModelFactory = messageViewModelFactory;
}
public void MessageReceived(string data) {
var messageViewModel = _messageViewModelFactory();
}
}
This way you are exposing dependencies of your ConversationViewModel class through the constrctor instead of hiding them inside the class implementation.
The IoC containers like Autofac provide way to inject Func in the constructor when you create object of ConversationViewModel using it.
I believe a better way to do that is by using interfaces. You can have both your real and mock ViewModels implement the same interface and use that interface everywhere where you would use a ViewModel class.
If it was me and I may not have all the information about your application but I would have a single ViewModel IConversationViewModel. And in the IConversationViewModel I would have a collection of IMessageModel instances. I would not go nesting ViewModels.
What you can do is create the MessageViewModel immediately in ViewModelLocator and register for receiving messages in MessageViewModel using the MVVMLight MessengerInstance in its constructor. Something like this:
public class ViewModelLocator
{
public class ViewModelLocator()
{
//creates instance immediately
SimpleIoc.Default.Register<MessageViewModel>(true);
}
}
public class MessageViewModel:ViewModelBase
{
public MessageViewModel()
{
MessengerInstance.Register<string>(this,DoSomething);
}
public void DoSomething(string data)
{
//do stuff
}
}
public class ConversationViewModel:ViewModelBase
{
public void MessageReceived(string data)
{
MessengerInstance.Send<string>(data);//this will trigger DoSomething in MessageViewModel
}
}
We have a large-ish app with a ribbon. The ribbon buttons are all bound to commands in my main view model (the data context of the main app window).
The constructor for MainViewModel is starting to grow as we create lots of RelayCommands (bound to the various ribbon commands). It looks something like this:
public MainWindowViewModel()
{
this.OpenProjectCommand = new RelayCommand(() =>
{
// buncha code
});
this.ProjectTypesCommand = new RelayCommand(() =>
{
// more code
});
this.NewSectionCommand = new RelayCommand(() =>
{
// code code code...
});
// ... only three ribbon buttons down, this is gonna get huge...
}
I'd prefer to have separate classes implementing each of the commands, rather than tons of inline code in MainViewModel's constructor. (Or creating lots of delegates in the MainViewModel, e.g. OpenProject, CanOpenProject, and then passing in references to them to the RelayCommand constructors).
Why don't I simply implement ICommand in a CommandBase and then create separate commands? Because I want to be "standard friendly" as per this question.
Is there a standard ICommand implementation I can use so that my commands are in separate classes?
I'd prefer not to add more MVVM frameworks into the mix since I'm already using MVVM Light. But I also don't want to reinvent the wheel.
Update: MainViewModel.cs doesn't need to be cluttered with scores of #regions or command methods. Extension methods aren't a good fit either IMHO.
The way I do is that I have "sub-viewmodels". For example, in the case of the MainViewModel, let's imagine that you have a PrintCommand and a CancelPrintCommand. You can have a new class called PrinterViewModel, and expose an instance of this class in the MainViewModel. Have the PrintCommand and the CancelPrintCommand in this PrinterViewModel (this also allows modular unit testing, which is neat).
Then in XAML:
Command="{Binding Main.Printer.PrintCommand}"
Alternatively, you could do
new RelayCommand(() => Printer.DoSomething())
Does that make sense?
Cheers
Laurent
You could at least create them in the getter.
You can use the ?? operator.
http://msdn.microsoft.com/en-us/library/ms173224.aspx
This basically says: Return _testCommand, but create it first if it's still null.
This way, the command is not created until it's needed!
public class TestViewModel : ViewModelBase
{
#region OpenCommand
private RelayCommand _testCommand;
public RelayCommand TestCommand {
get {
return _testCommand = _testCommand
?? new RelayCommand(
this.ExecuteOpenCommand,
this.CanOpenCommandExecute);
}
}
private void ExecuteOpenCommand()
{
// do stuff
}
private bool CanOpenCommandExecute()
{
return true;
}
#endregion
}
If your goal is to organize, you can use #region and #endregion. And like we said, if your goal is to shrink the constructing process, use the ?? operator in getters. If you just hate inline code, create private methods in combination with RelayCommand, in getters.
Most of the WPF mvvm applications, we are using ICommand in the view-model. But it is referring to System.Windows.Input. so the view-model is now tightly couple with System.Windows.Input namespace. according to my understanding view-model should be able to use in normal C# winform application or asp.net application.
Normally we are using following code lines to the command with RelayCommand implementation.
private RelayCommand testCommand;// or private ICommand testCommand;
public ICommand TestCommand
{
get
{
return testCommand ??
(testCommand = new RelayCommand(param => Test()));
}
}
public void Test()
{
}
What i feel is we need to remove all the ICommand and use RelayCommand instead. So we can eliminate the System.Windows namespace from the view-model. so final code will looks like this,
private RelayCommand testCommand;
public RelayCommand TestCommand
{
get
{
return testCommand ??
(testCommand = new RelayCommand(param => Test()));
}
}
public void Test()
{
}
Any suggestions on this approach? or is there any way to eliminate the System.Windows namespace from the view-model?
Any suggestions on this approach?
This still doesn't decouple you from System.Windows.Input as RelayCommand still must implement ICommand, even if it's indirectly implementing it.
Implementing ICommand within the ViewModel is one of those things that tends to be required in order to be pragmatic. Ideally, ICommand (or a similar interface) would have been implemented in a namespace that wasn't XAML specific. That being said, it is supported directly within the Portable Class Libraries, so it is not tied to a specific framework (WPF, Silverlight, Phone, etc) as much as XAML in general.
Pretty simple to avoid coupling your ViewModel to ICommand, if you want to. Probably not a bad idea, WPF will probably go the way of MFC one day. Overkill? maybe, but here is a how:
In your view:
<StackPanel>
<Button Command="{Binding Path=MyCommand}"> Do it! Kill me Now!</Button>
<TextBlock Text="{Binding Path=Message}"></TextBlock>
</StackPanel>
Inject your ViewModel into your DataContext, Take the responsibility for the native commands, out of your view model:
public class ViewModel : INotifyPropertyChanged
{
public string Message { get; set; }
public object MyCommand { get; set; }
public void OnMyCommand(object parameter)
{
Message += "I Ran something" + Environment.NewLine;
}
public bool CanMyCommand(object parameter)
{
return true;
}
// Injected Native Command handler
public ViewModel(ICommandFactory factory)
{
MyCommand = factory.CreateInstance(OnMyCommand, CanMyCommand);
}
public event PropertyChangedEventHandler PropertyChanged;
}
Note I'm using FODY to weave in the property change handler. INotifyPropertyChanged is System.dll btw.
Now, Bind this contract:
public interface ICommandFactory
{
object CreateInstance(Action<object> action, Func<object, bool> predicate);
}
... to something that will give you a native Command object;
public class NativeCommand : ICommand
{
private readonly Action<object> _action;
private readonly Func<object, bool> _predicate;
public NativeCommand(Action<object> action, Func<object, bool> predicate)
{
_action = action;
_predicate = predicate;
}
public bool CanExecute(object parameter)
{
return _predicate(parameter);
}
public void Execute(object parameter)
{
_action(parameter);
}
public event EventHandler CanExecuteChanged;
}
public class NativeCommandFactory : ICommandFactory
{
public object CreateInstance(Action<object> action, Func<object, bool> predicate)
{
return new NativeCommand(action, predicate);
}
}
Bind<ICommandFactory>().To<NativeCommandFactory>();
VoilĂ , decoupled commands.
Also note, your injection is done at initial application start. Your ViewModel is decoupled from whatever IoC container you choose.
Well, in theory, you are pretty much right. It would if nice of ICommand was completely UI-platform-independent.
But from a practical standpoint, if you are using MVVM in a WPF app, there's a pretty good chance you are fairly dependent on WPF's databinding and datatemplating capabilities anyway. Trying to stick a WinForms UI on top of something like that would likely require a significant amount of extra effort.
I've worked on some fairly large WPF/MVVM projects in the past. We considered MVVM to be a way of separating the specific details of the UI from the code - not so that we could switch to WinForms/ASP.NET/whatever, but so that we could change the look and feel of our UI (i.e. edit the XAML) without having to change the ViewModels. In this respect, MVVM worked perfectly.
If you are really concerned about sharing code across multiple types of projects, it might be better to try and put your common code in a typical 'Business Layer'-type class library, instead of in view model.
I have a ModuleLoader : NinjectModule which is where I bind everything.
Firstly I use
Bind<Form>().To<Main>();
to Bind a System.Windows.Forms.Form to my Main form.
Is this correct?
Secondly in the Program.cs I use this:
_mainKernel = new StandardKernel(new ModuleLoader());
var form = _mainKernel.Get<Main>();
Where _mainKernel is a ninject standard kernel.
Then I use Application.Run(form)
Is this correct?
I'm unsure as to what to bind together when it comes to Windows.Forms.
Thanks for any help.
You shouldn't really be binding to System.Windows.Forms.Form. Ninject is primarily meant for binding interfaces to concrete types so that you can pass around dependencies as interfaces and switch out the concrete implementation at runtime/during tests.
If you just want to use Ninject to create your Form in this way though, you'd simply use Bind<MyForm>().ToSelf() then do kernel.Get<MyForm>(). If you are requesting the concrete type directly though and it doesn't take any dependencies, there's not much point in using Ninject to initialise it.
In your situation, if your form implements an interface then you would do: Bind<IMainForm>().To<MainForm>() and request the interface type from Ninject. Usually your interface shouldn't be bound to the concept of a "form" though, it should be agnostic of the implementation (so later you could produce a CLI and website version and simply swap the Ninject bindings).
You could use the Model-View-Presenter design pattern (or a variant) to achieve this like:
public interface IUserView
{
string FirstName { get; }
string LastName { get; }
}
public class UserForm : IUserView, Form
{
//initialise all your Form controls here
public string FirstName
{
get { return this.txtFirstName.Text; }
}
public string LastName
{
get { return this.txtLastName.Text; }
}
}
public class UserController
{
private readonly IUserView view;
public UserController(IUserView view)
{
this.view = view;
}
public void DoSomething()
{
Console.WriteLine("{0} {1}", view.FirstName, view.LastName);
}
}
Bind<IUserView>().To<UserForm>();
Bind<UserController>().ToSelf();
//will inject a UserForm automatically, in the MVP pattern the view would inject itself though
UserController uc = kernel.Get<UserController>();
uc.DoSomething();