One small change that was made in Prism 4 was to update the DelegateCommand class to deal with command parameters a little more cleanly, and also to update the weak reference handling inside the DelegateCommand to work correctly based on the way Silverlight 4 implemented command hookup as opposed to WPF. Here is the scoop.
Command Parameters with DelegateCommand Need to Be Nullable
The ICommand.Execute and ICommand.CanExecute methods take a single parameter of type object. That parameter can be populated with a parameter by setting the CommandParameter property of a command source (such as a Button) to some object. However, because it is defined in terms of object and may never be set, the pattern establishes that the argument should be nullable.
a) The view might not actually set the CommandParameter at all
b) Even if the CommandParameter is set to a Binding, at parse time the Binding might not resolve to a value yet and could pass a null when CanExecute is initially called.
But the strong typing on the DelegateCommand also made it look like it should be fine to do something like hook up to a DelegateCommand
This is now fixed in Prism 4, although maybe not in the way you would expect. The Prism team initially looked into finding a way to just make it work with value types. But there was not really a way to do that without violating the principal of least surprise in some cases. The command method signatures imply nullability by being defined in terms of type object. Putting a strongly typed wrapper on there to avoid having to cast the parameters yourself is a nice convenience, but shouldn’t change the semantics of the underlying interface.
So the fix in Prism 4 is that the constructor of DelegateCommand
So the bad news is that if you had code that worked OK before passing value types for T with DelegateCommand
DelegateCommand (Not of T)
Another common request in Prism was to have a non-generic DelegateCommand class. If you never intend to pass an argument, it was a pain to always have to declare your commands in terms of DelegateCommand and then have a signature in your Execute and CanExecute handlers that took an object parameter that you always ignored. Now if you never expect a parameter to be passed to your command handlers, you can just define your command in terms of DelegateCommand, and the Execute and CanExecute handlers can just have no parameters (Action and Func
Because of this, you will also see that the common functionality is factored out to a DelegateCommandBase class that both DelegateCommand and DelegateCommand
One of the things the DelegateCommand does for you in Prism is that it tries to help protect you from leaking memory if the lifetimes of the command source (i.e. Button in a view) and the command handler (i.e. target method in a view model) are different. For example, in some scenarios, you might choose to keep an instance of a view model around in memory, and create new instances of a view and bind each instance of the view to the view model only when it is being shown.
Until Silverlight 4, there were no built in command handlers, so this was really only relevant to WPF anyway. And WPF does things a little differently under the covers than the implementation that ended up in Silverlight 4. In WPF, in addition to holding a reference to the command object itself ( so that Execute and CanExecute can be called), the command source (i.e. Button) holds a reference to the delegate instance that exposed the CanExecuteChanged event (which would be something like your view model, as opposed to the command object itself). Silverlight 4 does not hold that additional reference.
So that required a small change that you might run across if you are looking at the code, where the DelegateCommand uses a weak reference wrapper to command source when you are in WPF and not in Silverlight. This is to accommodate this difference in the platforms.
Bottom line, the weak reference is used in WPF to avoid leaking memory if the command source comes and goes and the command target sticks around, but not used in Silverlight because it is not needed.
That is about it as far as changes to commands. Bottom line, any code you had before should work as it was unless you were using value types as parameters. In that case you will need to change them to take Nullable