I have been noticeably absent lately and I just thought I’d drop in and explain that I haven’t given up blogging, I’ve just been crazy busy. I’ve been working mostly on a side project in my free time and I’ve been very busy trying to get up to speed on Java. My current client has a legacy application that was written in Java and everyone in the department is a .NET developer. For many complicated reasons I won’t bore you with I’ve been elected to do some maintenance on the project. But I hope to glean a few posts on learning Java and getting my environment setup from a .NET developer’s perspective. If I do I’ll probably do something along the lines of my “Lost In Translation” series of posts I did this time last year on Oracle.
Also, I haven’t forgotten about my MVVM series and I still plan on finishing out the series in the next month or two. I still have to cover EventAggregator and possibly more details on my service wrapper and where I came up with the design for it.
Until then I am at least back to monitoring for any comments and responding. C-ya soon.
Source Code
I have to apologize for the length of this article. I wanted to split it into two separate parts, but the way I ended up writing it all just seems difficult to split it now that I’m done. Hopefully the section headings are clear enough for those who are only interested in specifics can find what they are looking for.
This is part 6 in my series on implementing MVVM with the Prism Framework (CompositeWPF). This time we’re going to discuss Commands. You can think of Commands as an abstraction of Events, but don’t confuse the two. An Event is fired by a single publisher and anyone who is interested in that event may subscribe to it. With regards to the UI, a Button has a Click event. If you want to handle that click event you subscribe to it by creating an event handler which will be called when the event fires. Your event handler can then perform an action whenever it is called in response to the event to which it is subscribed. In other words, if you subscribe to the Button.Click event your event handler will be called anytime the Button is clicked. Additionally, other objects interested in the Click event of the button may be notified and they will also be able to perform other operations when the Click event fires.
A command is technically the opposite. The command itself performs a specific operation and the command is exposed as part of a public interface which can be called to execute that operation. It can be called by any object which can access the command but it provides no means to subscribe to the command or notifications that it has been called. The command itself is actually more analogous to the event handler than it is to the event. But the way you wire it up seems familiar to those used to wiring up events and event handlers using the Visual Studio designer. When wiring up a Command to a Button object you use an attached property to bind the UI element to the Command, similar to the way you can use the OnClick attribute of the Button element to declare an event handler you wish to be called when the Button is clicked.
Event Example
<Button Content="Send" Click="Button_Clicked" />
Command Example
<Button Content="Send" VerticalAlignment="Top" Width="100"
cmd:Click.Command="{Binding SendMessage}" />
WPF and Silverlight both provide an interface named ICommand which is defined this way:
using System;
namespace System.Windows.Input
{
// Summary:
// Defines the contract for commanding,
// using the same contract as used in WPF.
public interface ICommand
{
// Summary:
// Occurs when changes occur that affect
// whether the command should execute.
event EventHandler CanExecuteChanged;
// Summary:
// Defines the method that determines
// whether the command can execute in its
// current state.
//
// Parameters:
// parameter:
// Data used by the command. If the
// command does not require data to be passed,
// this object can be set to null.
//
// Returns:
// true if this command can be executed;
// otherwise, false.
bool CanExecute(object parameter);
//
// Summary:
// Defines the method to be called when the
// command is invoked.
//
// Parameters:
// parameter:
// Data used by the command. If the command
// does not require data to be passed,
// this object can be set to null.
void Execute(object parameter);
}
}
The important parts of the interface are the Execute and CanExecute methods. Execute is the method which will be called and CanExecute indicates wither or not the Command is currently active. For example, if you don’t want the user clicking on the Save button which is bound to your SaveCommand then you can provide logic in the CanExecute method which will only return true when the state of your ViewModel (or the data model exposed by your ViewModel) is “modified”. If CanExecute returns “false” then WPF/Silverlight will disable the button until CanExecute returns “true”.
Exposing Commands
In order to bind a UI element to a command first you must provide a command from your View-Model. Prism provides an implementation of ICommand named DelegateCommand<T>. When implementing MVVM you will want to use a command implementation other than RoutedCommand provided by WPF. The reason for this is because RoutedCommand is tied to the UI and you will possibly experience some difficulties using RoutedCommand with MVVM as your application grows in complexity and you try to keep your views modular. If you want more details on what those issues are, see the Prism documentation for “Commands”. Most of my experience has been with Silverlight, which is why I defer to the Prism docs. Silverilght doesn’t have an implementation of ICommand, so no RoutedCommand. For that reason, I would most likely say something wrong since I don’t really have any experience with it.
DelegateCommand<T> provides a UI agnostic means of exposing your commands to the View. And because it uses Generics it also allows you to work with strongly typed parameters. Here’s how I’ve implemented the SendMessage command in the sample application I have provided with this series:
public EditorViewModel(IMessageServiceAsync service,
IEventAggregator aggregator)
{
m_MessageService = service;
// ... other setup code ...
SendMessage = new DelegateCommand<String>(
SendMessageExecute, SendMessageCanExecute);
}
public ICommand SendMessage { get; set; }
private void SendMessageExecute(String arg)
{
Message message = new Message
{
Content = arg,
Date = DateTime.Now
};
IAsyncResult result = m_MessageService.BeginAddMessage(
message, new AsyncCallback(EndSendMessage), null);
if (result.CompletedSynchronously)
EndSendMessage(result);
}
private bool SendMessageCanExecute(String arg)
{
return !String.IsNullOrEmpty(Message.Content);
}
private void EndSendMessage(IAsyncResult result)
{
m_MessageService.EndInvoke(m => m.EndAddMessage(result));
}
As you can see CanExecute will only return true when the the Message property of our ViewModel is not null or empty. In our view the Message property is bound to the TextBox where the user will enter the message they wish to send.
Command Parameters
In the last code snippet you may have noticed that Execute and CanExecute accept a string parameter. The ICommand interface declares these as simple object type parameters, but DelegateCommand<T> provides the strongly typed version for us. Either way, because of the parameters we can make our Command a bit more flexible (not that we need it in this situation). Prism provides a second attached property which allows you to bind a value to the parameter for ICommand.Execute. If you are using WPF or Silverlight 3 you could bind to the TextBox’s Text property or any other element on your UI. If you’re using Silverlight 2 you can only bind to a StaticResource or some public property of the Button’s DataContext.
<Button Content="Send" VerticalAlignment="Top" Width="100"
cmd:Click.Command="{Binding SendMessage}"
cmd:Click.CommandParameter="{Binding Path=CurrentMessage.Content}" />
Using Command Parameters like this allows you to, for example, add a button to each item of a list and pass the object bound to the DataContext of each item to the Command on your view model. When a button is clicked the correct object will be passed as an argument to the Execute method.
Service Client Communication
Many of the commands you define will be backed by an external web service and given that Visual Studio provides a nice wizard to connect to a web service and generate a client proxy to communicate with any service I have been asked why I don’t use the “Add Service Reference” utility provided by Visual Studio or SvcUtil.exe provided with the .NET Framework SDK. Personally, I don’t like the messy designer file generated by the utility. I don’t have full control over the namespace generated and I found mocking the interfaces to be a pain. Many of the examples which demonstrate using the proxy generated by the utility look like this:
private void GetMessagesExecute(Object arg)
{
MessageServiceClient client = new MessageServiceClient();
client.GetMessagesCompleted += new EventHandler<GetMessagesCompletedEventArgs>(client_GetMessagesCompleted);
client.GetMessagesAsync();
}
void client_GetMessagesCompleted(object sender, GetMessagesCompletedEventArgs e)
{
ObservableCollection<Message> result = e.Result;
}
There are some nice features here. First and foremost, you don’t have to worry about the UI thread. When the completed event fires you don’t have to get a reference to the Dispatcher to update properties which raise INotifyPropertyChanged or INotifyCollectionChanged. It makes things nice and clean. But you can’t mock this class. I’ve tried and it requires practically writing the whole thing myself. The generated proxy has an interface which matches the interface I defined for my service, but there is no interface which exposes the “MyMethodCompleted” events or the “MyMethodAsync” methods. So if I want to be able to write unit tests which are independent of any external dependencies then I cannot use the Async/Completed model, I must use the Begin/End Async patterns. And if I am going to use those anyway then why mess with a generated proxy when all it requires is a single line of code to create my service proxy:
IMessageServiceAsync service = new ChannelFactory<IMessageServiceAsync>(
"BasicHttpBinding_IMessageEndpoint").CreateChannel();
To support this, there is an extra few steps:
- I must define an Async version of my Service Contract
- If I am using Silverlight I must add a link to not only the file which contains Async Service Contract definition but also the class files which define the types returned by my service.
- If I change my Service Contract I must mirror the change in the Async version of my Service Contract.
But except for maintaining an async version of my Service Contract these are one time setup steps that really don’t take much time. And as for maintaining an async interface, it really doesn’t take any more time than it does to remove the service reference and re-add it. For me it is worth the time saved trying to create the mock objects needed to properly test in isolation. We are all generally allergic to additional typing but in the end I find that doing it this way saves me time in the long run.
Protecting from Faults
For a long time I was uncomfortable with just using the raw ClientChannel object provided for me. When applications are deployed in the wild, stuff happens and you want a clean way for your application to recover. For example, when you experience a Fault in your communication with the service you need to properly clean up the communication channel. But what do you do if you still need to communicate with the service. You need a new channel for communication. But in our scenario the ViewModel doesn’t know how to create the channel. So how do we properly handle faults and recover gracefully from them without requiring our user to do anything?
using System;
using System.Collections.Generic;
using System.ServiceModel;
using CodeCamp.Model;
namespace CodeCamp.Common.Services
{
public class MessageServiceWrapper : IMessageServiceAsync, IDisposable
{
private ChannelFactory<IMessageServiceAsync> m_Factory;
private IMessageServiceAsync m_Service;
private Object m_SyncRoot = new Object();
public MessageServiceWrapper(String endpointName)
{
m_Factory = new ChannelFactory<IMessageServiceAsync>(endpointName);
}
private void CloseChannel()
{
if (m_Service != null)
{
lock (m_SyncRoot)
{
if (m_Service != null)
{
try
{
IClientChannel channel = (IClientChannel)m_Service;
channel.Faulted -= IClientChannel_Faulted;
if (channel.State == CommunicationState.Faulted)
channel.Abort();
else
channel.Close();
channel.Dispose();
}
catch (CommunicationException) { }
catch (TimeoutException) { }
m_Service = null;
}
}
}
}
private IMessageServiceAsync Current
{
get
{
if (m_Service != null)
return m_Service;
lock (m_SyncRoot)
{
if (m_Service == null)
{
m_Service = m_Factory.CreateChannel();
((IClientChannel)m_Service).Faulted += IClientChannel_Faulted;
}
}
return m_Service;
}
}
private void IClientChannel_Faulted(Object sender, EventArgs e)
{
CloseChannel();
}
#region IMessageServiceAsync Members
public IAsyncResult BeginAddMessage(Message message,
AsyncCallback callback, object asyncState)
{
return Current.BeginAddMessage(message, callback, asyncState);
}
public void EndAddMessage(IAsyncResult result)
{
try
{
Current.EndAddMessage(result);
}
catch
{
CloseChannel();
throw;
}
}
public IAsyncResult BeginGetMessages(AsyncCallback callback,
object asyncState)
{
return Current.BeginGetMessages(callback, asyncState);
}
public IList<Message> EndGetMessages(IAsyncResult result)
{
try
{
return Current.EndGetMessages(result);
}
catch
{
CloseChannel();
throw;
}
}
#endregion
#region IDisposable Members
private Boolean m_IsDisposed = false;
public void Dispose()
{
if (m_IsDisposed)
throw new ObjectDisposedException("MessageServiceWrapper");
CloseChannel();
((IDisposable)m_Factory).Dispose();
m_IsDisposed = true;
}
#endregion
}
}
My first attempt at this was to create a wrapper class for each service I used on my client. The problem was it was too much work. I had to maintain the proper methods and signatures to keep my contracts in sync with my interfaces. This had to be done for every operation on every service. I really didn’t like this method at all.
So I created a base class which helped a little, but I still had to keep the interface in sync.
ClientChannelWrapper.cs
using System;
using System.Collections.Generic;
using System.ServiceModel;
using CodeCamp.Model;
namespace CodeCamp.Common.Services
{
public class ClientChannelWrapper<T> : IDisposable where T : class
{
private ChannelFactory<T> m_Factory;
private T m_Service;
private Object m_SyncRoot = new Object();
public ClientChannelWrapper(String endpointName)
{
m_Factory = new ChannelFactory<T>(endpointName);
}
protected void CloseChannel()
{
if (m_Service != null)
{
lock (m_SyncRoot)
{
if (m_Service != null)
{
IClientChannel channel = (IClientChannel)m_Service;
try
{
channel.Faulted -= IClientChannel_Faulted;
if (channel.State == CommunicationState.Faulted)
channel.Abort();
else
channel.Close();
}
catch (CommunicationException) { channel.Abort(); }
catch (TimeoutException) { channel.Abort(); }
catch (Exception) { channel.Abort(); throw; }
finally { m_Service = null; }
}
}
}
}
protected T Current
{
get
{
if (m_Service != null)
return m_Service;
lock (m_SyncRoot)
{
if (m_Service == null)
{
m_Service = m_Factory.CreateChannel();
((IClientChannel)m_Service).Faulted += IClientChannel_Faulted;
}
}
return m_Service;
}
}
private void IClientChannel_Faulted(Object sender, EventArgs e)
{
CloseChannel();
}
#region IDisposable Members
private Boolean m_IsDisposed = false;
public void Dispose()
{
if (m_IsDisposed)
throw new ObjectDisposedException("ClientChannelWrapper");
try
{
CloseChannel();
}
finally
{
m_IsDisposed = true;
}
}
#endregion
}
}
MessageServiceWrapper.cs
using System;
using System.Collections.Generic;
using CodeCamp.Common.Services;
using CodeCamp.Model;
namespace CodeCamp.Services
{
public class MessageServiceWrapper : ClientChannelWrapper<IMessageServiceAsync>, IMessageServiceAsync
{
public MessageServiceWrapper(string endPointName)
: base(endPointName)
{
}
public MessageServiceWrapper()
: base("BasicHttpBinding_IMessageEndpoint")
{
}
#region IMessageServiceAsync Members
public IAsyncResult BeginAddMessage(Message message, AsyncCallback callback, object asyncState)
{
try
{
return Current.BeginAddMessage(message, callback, asyncState);
}
catch
{
CloseChannel();
throw;
}
}
public void EndAddMessage(IAsyncResult result)
{
try
{
Current.EndAddMessage(result);
}
catch
{
CloseChannel();
throw;
}
}
public IAsyncResult BeginGetMessages(AsyncCallback callback, object asyncState)
{
try
{
return Current.BeginGetMessages(callback, asyncState);
}
catch
{
CloseChannel();
throw;
}
}
public IList<Message> EndGetMessages(IAsyncResult result)
{
try
{
return Current.EndGetMessages(result);
}
catch
{
CloseChannel();
throw;
}
}
#endregion
}
}
This wasn’t much better, it did help but I knew I couldn’t really use this in any more than a trivial application with few or only one service. But I’ve been reading a bit on functional programming (not enough to write F# code or Haskell or anything for that matter) and I ran into this article by Jeremy Miller. He demonstrates using a technique to reduce the need to write so much boilerplate code required to call a repository. So I sacrificed a little cleanliness in my interfaces and came up with this:
IClientChannelWrapper.cs
using System;
namespace CodeCamp.Common.Services
{
public interface IClientChannelWrapper<T> where T : class
{
IAsyncResult BeginInvoke(Func<T, IAsyncResult> function);
void Dispose();
void EndInvoke(Action<T> action);
TResult EndInvoke<TResult>(Func<T, TResult> function);
}
}
ClientChannelWrapper.cs
using System;
using System.Collections.Generic;
using System.ServiceModel;
using CodeCamp.Model;
namespace CodeCamp.Common.Services
{
/// <summary>
/// Wrapper class ensures proper life-cycle handling for IClientChannel
/// objects by implementing proper Open, Close and Dispose techniques
/// based on recommended practices.
/// </summary>
/// <remarks>
/// The idea for BeginInvoke and EndInvoke methods was derived from
/// this <see cref="http://msdn.microsoft.com/en-us/magazine/ee309512.aspx">MSDN article</see>
/// </remarks>
/// <typeparam name="T">An interface which defines an async ServiceContract</typeparam>
public class ClientChannelWrapper<T> : IDisposable, IClientChannelWrapper<T> where T : class
{
private ChannelFactory<T> m_Factory;
private T m_Service;
private Object m_SyncRoot = new Object();
public ClientChannelWrapper(String endpointName)
{
m_Factory = new ChannelFactory<T>(endpointName);
}
public ClientChannelWrapper(T service)
{
m_Service = service;
}
public IAsyncResult BeginInvoke(Func<T, IAsyncResult> function)
{
try
{
return function.Invoke(Current);
}
catch (Exception)
{
CloseChannel();
throw;
}
}
public TResult EndInvoke<TResult>(Func<T, TResult> function)
{
try
{
return function.Invoke(Current);
}
catch (Exception)
{
CloseChannel();
throw;
}
}
public void EndInvoke(Action<T> action)
{
try
{
action.Invoke(Current);
}
catch (Exception)
{
CloseChannel();
throw;
}
}
protected void CloseChannel()
{
if (m_Service != null)
{
lock (m_SyncRoot)
{
if (m_Service != null)
{
IClientChannel channel = m_Service as IClientChannel;
if (channel != null)
{
try
{
channel.Faulted -= IClientChannel_Faulted;
if (channel.State == CommunicationState.Faulted)
channel.Abort();
else
channel.Close();
}
catch (CommunicationException) { channel.Abort(); }
catch (TimeoutException) { channel.Abort(); }
catch (Exception) { channel.Abort(); throw; }
finally { m_Service = null; }
}
}
}
}
}
protected T Current
{
get
{
if (m_Service != null)
return m_Service;
lock (m_SyncRoot)
{
if (m_Service == null)
{
m_Service = m_Factory.CreateChannel();
((IClientChannel)m_Service).Faulted += IClientChannel_Faulted;
}
}
return m_Service;
}
}
private void IClientChannel_Faulted(Object sender, EventArgs e)
{
CloseChannel();
}
#region IDisposable Members
private Boolean m_IsDisposed = false;
public void Dispose()
{
if (m_IsDisposed)
throw new ObjectDisposedException("ClientChannelWrapper");
try
{
CloseChannel();
}
finally
{
m_IsDisposed = true;
}
}
#endregion
}
}
And here’s how you use it :
Create/Register ClientChannelWrapper
IClientChannelWrapper<IMessageServiceAsync> service = new ClientChannelWrapper<IMessageServiceAsync>("BasicHttpBinding_IMessageEndpoint");
m_Container.RegisterInstance<IClientChannelWrapper<IMessageServiceAsync>>(service);
Reference ClientChannelWrapper
public class EditorViewModel : IEditorViewModel
{
private IClientChannelWrapper<IMessageServiceAsync> m_MessageService;
public EditorViewModel(IClientChannelWrapper<IMessageServiceAsync> service,
IEventAggregator aggregator)
{
m_MessageService = service;
// ... other ctor stuff ...
}
Use ClientChannelWrapper
IAsyncResult result = m_MessageService.BeginInvoke(
m => m.BeginAddMessage(message, new AsyncCallback(EndSendMessage), null));
What this does for us is that all our service calls can now be wrapped in try/catch blocks which will auto-magically clean up the connection correctly (call Abort - can’t call Dispose) if there is a fault. Then you can gracefully catch the exception and recover. When you retry a new client channel will be created for you without any knowledge on the part of your ViewModel.
Mind Your UI Thread
If you aren’t using a generated client proxy or if you are doing any other kind of asynchronous calls (like sockets) you need to be aware of the UI thread. Making your UI more responsive by performing long running tasks on a background thread is all well and good. However, when your operation completes and you need to update your ViewModel you must keep in mind that your UI is running on a static thread and can’t be updated from a background thread. Basically this means any public properties on your ViewModel which will raise INotifyPropertyChanged or INotifyCollectionChanged cannot be updated by your background thread. So how do you update them if our ViewModel doesn’t know anything about the UI?
I have defined an interface I call IDispatcher:
using System;
namespace CodeCamp.Common
{
public interface IDispatcher
{
void BeginInvoke(Action action);
void BeginInvoke(Delegate action, params Object[] args);
}
}
Then I have a concrete class called DispatcherFacade which allows me to pass in a flag telling it if the application is running on a UI thread or if is running in a test environment or design mode. If the application UI is not running (false) then the action or delegate is invoked on the current thread. If the UI is running (true) then it gets a reference to the UI thread and executes the delegate on the UI thread:
using System;
using System.Windows;
namespace CodeCamp.Common
{
public class DispatcherFacade : IDispatcher
{
private Boolean m_IsHtmlEnabled;
public DispatcherFacade(Boolean isHtmlEnabled)
{
m_IsHtmlEnabled = isHtmlEnabled;
}
#region IDispatcher Members
public void BeginInvoke(Action action)
{
if (m_IsHtmlEnabled == false)
action.Invoke();
Deployment.Current.Dispatcher.BeginInvoke(action);
}
public void BeginInvoke(Delegate action, params object[] args)
{
if (m_IsHtmlEnabled == false)
action.DynamicInvoke(args);
Deployment.Current.Dispatcher.BeginInvoke(action, args);
}
#endregion
}
}
This keeps me from having to write code which is dependent upon the UI and I don’t have to write a mock for IDispatcher as DispatcherFacade handles all three situations.
Why Check IAsyncResult.CompletedSyncronously ?
private void GetMessagesExecute(Object arg)
{
IAsyncResult result = m_MessageService.BeginInvoke(
m => m.BeginGetMessages(new AsyncCallback(EndGetMessages), null));
if (result.CompletedSynchronously)
EndGetMessages(result);
}
You’ll notice whenever I make a call to a BeginXX async method I check the CompletedSyncronously property. If it’s “true” then I call my EndXX AsyncCallback method. The reason for this is to simplify testing. Writing tests for asynchronous method calls is a pain, this way my tests are cleaner and self-contained in a single method without having to account for race conditions caused by a different environment (test vs. runtime). In order for this to work I just needed to implement my own version of IAsyncResult:
using System;
using System.Threading;
namespace CodeCamp.Common.Utility
{
public class MockAsyncResult : IAsyncResult
{
#region IAsyncResult Members
private Object m_AsyncState;
public object AsyncState
{
get { return m_AsyncState; }
set { m_AsyncState = value; }
}
ManualResetEvent m_WaitHandle = new ManualResetEvent(true);
public System.Threading.WaitHandle AsyncWaitHandle
{
get { return m_WaitHandle; }
}
public bool CompletedSynchronously
{
get { return true; }
}
public bool IsCompleted
{
get { return true; }
}
#endregion
}
}
Then in my mock service implementation I use it like this:
using System;
using System.Collections.Generic;
using CodeCamp.Model;
namespace CodeCamp.Common.Utility
{
public class MockMessageService : IMessageServiceAsync
{
#region IMessageServiceAsync Members
public IAsyncResult BeginGetMessages(AsyncCallback callback, object state)
{
return new MockAsyncResult { AsyncState = state };
}
public System.Collections.Generic.IList<Message> EndGetMessages(IAsyncResult result)
{
return new List<Message> {
new Message { Content = "Message 1", Date = new DateTime(2009, 1, 1, 15, 02, 35) },
new Message { Content = "Message 2", Date = new DateTime(2009, 1, 1, 15, 08, 21) },
new Message { Content = "Message 3", Date = new DateTime(2009, 1, 1, 15, 11, 01) }
};
}
public IAsyncResult BeginAddMessage(Message message, AsyncCallback callback, object state)
{
return new MockAsyncResult { AsyncState = state };
}
public void EndAddMessage(IAsyncResult result)
{
return;
}
#endregion
}
}
This also makes it easier to support design-time databinding because I make sure to call my AsyncCallback directly.
Conclusion
A lot has been covered in this last post. I wasn’t able to cover as much as I would have liked because it was just getting too long. If you have questions specific to anything in this article or series I’ll be happy to clarify.
We’re almost to the end of our series. In my next post, the last one, I’ll be looking at events using the EventAggregator and we’ll be using it to provide a global error handler to recover gracefully from unhandled exceptions.
Source Code
tags: Silverlight, MVVM, Prism, MVVM with Prism 101, ICommand, WCF Client Proxy
Source Code
Now that we’ve seen the View-Model in Part 5, how do we wire up the View-Model to the View? As any developer worth his salt would say, “it depends” (I’m trying to raise my worth to at least the value of salt ;) ).
Inversion of Control
First, let me define a few things. First, Inversion of Control is a pattern wherein creation of objects is delegated in an effort to simplify instantiation and/or defer it until runtime. Huh? Inversion of Control is a means of programming against interfaces. Your classes reference interfaces at design-time and then delegate the creation of the concrete classes to a single component or service. The result is you now have a only a single dependency – the “Container” – instead of a complex hierarchy of dependencies:
public class ServiceA() {
public ServiceA(){ //... }
}
public class ServiceB() {
public ServiceB(ServiceA, ServiceD){ //... }
}
public class ServiceC(ServiceA) {
public ServiceC(){ //... }
}
public class ServiceD(ServiceA) {
public ServiceD(){ //... }
}
public class Consumer {
private ServiceB m_ServiceB;
private ServiceC m_ServiceC;
public Consumer() {
ServiceA serviceA = new ServiceA();
ServiceD serviceD = new ServiceD(serviceA);
m_ServiceB = new ServiceB(serviceA, serviceD);
m_ServiceC = new ServiceC(serviceA);
}
}
The example above is not uncommon. Not only is it difficult to test, but if any of the classes require a change in constructor parameters or you want to change which service you’re referencing you’ve got to clean up every consumer class which uses the service you just changed. We’re looking at a high level of complexity and a very brittle implementation.
Most often Inversion of Control uses an object called a “Container” which is responsible for building these dependency hierarchies. The Container allows you to defer the creation of concrete classes until runtime. At some point before your class is instantiated, the Container is configured – most often either in your startup process or in a config file – with the mappings between your interfaces and the concrete implementations of your classes. Then when you need to get a reference to the concrete implementation of an interface or just create a new instance of a standard class you use the Container to wire everything up. For example, given the example above you can do either of the following:
1: ServiceB m_ServiceB = Container.Resolve<ServiceB>(); // Create a new instance of a concrete class
2: ISomeInterface m_SomeObject = Container.Resolve<ISomeInterface>(); // get a concrete instance of an interface
The first example may have you saying why use Container.Resolve<ServiceB>() instead of new ServiceB()? Well, given the definitions above, you’d actually need to do this:
ServiceA serviceA = new ServiceA;
ServiceD serviceD = new ServiceD;
ServiceB m_ServiceB = new ServiceB(serviceA, serviceD);
Using the Container is much cleaner. As for line 2, you really see the power of IoC where your code isn’t tied to any concrete implementation at all. This makes testing very simple and your code becomes very, very flexible.
Dependency Injection
Here’s a term around which there can be much confusion. It seems at times that it is synonymous with Inversion of Control (IoC), a term I have used some here in this series. It is true you don’t often see one without the other, but they are not the same.
Dependency Injection refers explicitly to the way you use IoC. Constructor Injection is the form of Dependency Injection you will see used in Prism. Other forms of Dependency Injection are Setter Injection and Interface Injection. I really don’t use these and so instead of floundering for when and how to use them I’ll refer you to Martin Fowler for more on these alternative forms of Dependency Injection.
public class ServiceA() : InterfaceA {
public ServiceA(){ //... }
}
public class ServiceB() : InterfaceB {
public ServiceB(InterfaceA, InterfaceD){ //... }
}
public class ServiceC(InterfaceA) : InterfaceC {
public ServiceC(){ //... }
}
public class ServiceD(InterfaceA) : InterfaceD {
public ServiceD(){ //... }
}
public class Consumer {
private InterfaceB m_ServiceB;
private InterfaceC m_ServiceC;
public Consumer(InterfaceB, InterfaceC) {
m_ServiceB = InterfaceB;
m_ServiceC = InterfaceC;
}
}
In this last example all the services implement interfaces and our consumer then accepts those interfaces as arguments to the constructor. In order to call Container.Resolve<Consumer>() we need to register our services with the container. You can do this either in your Bootstrapper or an IModule implementation like this:
Container.RegisterType<InterfaceA, ServiceA>();
Container.RegisterType<InterfaceB, ServiceB>();
Container.RegisterType<InterfaceC, ServiceC>();
Container.RegisterType<InterfaceD, ServiceD>();
Now you can create an instance of the Consumer class anywhere in your application with a single line of code. Also, when you test Consumer you can replace the actual implementation of the services with mock versions which allow you to test Consumer in isolation.
Dependency Injection with Prism
So how do we use Dependency Injection in a Prism application? It’s easy, here’s how:
EditorView.xaml.cs (code behind)
using System.Windows.Controls;
using CodeCamp.Common.ViewModel;
namespace CodeCamp.Editor
{
public partial class EditorView : UserControl
{
public EditorView(EditorViewModel model)
{
InitializeComponent();
this.DataContext = model;
}
}
}
EditorModule.cs
using CodeCamp.Common.ViewModel;
using Microsoft.Practices.Composite.Modularity;
using Microsoft.Practices.Composite.Regions;
using Microsoft.Practices.Unity;
namespace CodeCamp.Editor
{
public class EditorModule : IModule
{
private IRegionManager m_Manager;
public EditorModule(IRegionManager manager)
{
m_Manager = manager;
}
#region IModule Members
public void Initialize()
{
m_Manager.RegisterViewWithRegion("MainRegion", typeof(EditorView));
}
#endregion
}
}
You should recognize the code in EditorModule.cs from part 4 of this series. Here we’re not doing anything but telling Prism to load EditorView into the MainRegion region of our Shell. From there Prism takes over by using the Unity IoC Container to create an instance of our EditorViewModel class and pass it to the EditorView constructor during the build process. Then the EditorView class takes the reference to EditorViewModel and sets it as the DataContext for the View. From there all we need to do is declare our bindings in Xaml:
EditorView.xaml
<UserControl x:Class="CodeCamp.Editor.EditorView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cmd="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation"
xmlns:controls="clr-namespace:CodeCamp.Common.Controls;assembly=CodeCamp.Common"
Width="400" Height="25">
<StackPanel Orientation="Horizontal">
<StackPanel x:Name="LayoutRoot" Background="White" Orientation="Horizontal" DataContext="{Binding Path=CurrentMessage}">
<TextBlock>Message:</TextBlock>
<TextBox Width="200" Text="{Binding Path=Content, Mode=TwoWay}" VerticalAlignment="Top" />
<controls:ErrorStatus PropertyName="Content" />
</StackPanel>
<Button Content="Send" VerticalAlignment="Top" Width="100"
cmd:Click.Command="{Binding SendMessage}"
cmd:Click.CommandParameter="{Binding Path=CurrentMessage.Content}" />
</StackPanel>
</UserControl>
Nothing to it. You could refactor an interface from EditorViewModel. For me, sometimes I do sometimes I don’t. There isn’t a need for it, since if you’re able to keep your View clear of any logic then there isn’t anything to test. If there’s nothing to test then, in the case of the View there is no need to ever substitute a mock of EditorViewModel for the real thing. In our sample application I use interfaces because it demonstrates the principal of registering types and allowing the IoC Container to resolve those types at runtime, but unless there is a reason you need to be able to substitute concrete objects and mock objects you can keep it simple here.
ServiceLocator
With ServiceLocator you can remove the dependency on the Container. ServiceLocator is a static class with properties which expose your service interfaces. Your ServiceLocator becomes your dependency. It knows about which concrete classes map to which interfaces. When you get the value of a property ServiceLocator will return the concrete implementation:
public class ServiceLocator {
public static InterfaceA {
get{ return new ServiceA(); }
}
public static InterfaceB {
get{
return new ServiceB(
ServiceLocator.InterfaceA,
ServiceLocator.InterfaceD
);
}
}
public static InterfaceC {
get{
return new ServiceC(
ServiceLocator.InterfaceA
);
}
}
public static InterfaceD {
get{
return new ServiceC(
ServiceLocator.InterfaceA
);
}
}
}
You get the same benefits of Dependency Injection, without the dependence on the Container.
In my view Dependency Injection requires less work. With ServiceLocator you need to write the class, then you will also need to maintain a separate version of that class that returns mock objects for testing purposes. For that reason, I prefer Dependency Injection over ServiceLocator. So why bother bringing it up then?
Design-Time Databinding
ServiceLocator is great for providing sample data which can be used during design-time to allow you to be more productive. Without it you will more often than not spend a lot of time in the modify-build-run-modify cycle where every change or tweak you make requires you to run the application to see what it actually looks like. However, Blend (and now the upcoming VS 2010) has a designer which gives you a view of what your view will actually look like without running it. Blend 3 has a sample data feature which allows you to bind to a sample data source when you’re designing your view, but this requires you to maintain sample data for test scenarios as well as for the designer. Using a ServiceLocator to provide a reference to your View-Model which has been provided with mock data means you are designing your view using data that will pass through your actual View-Model. This means your design-time experience is realistic and you can have a single source of mock data that can be used for both testing and designing. \
In the sample project I am using along with this series HistoryView uses this technique.
HistoryViewModel.cs (ctor)
public HistoryViewModel(IMessageServiceAsync messageService)
{
// store parameters as local member variables
}
MockMessageService.cs
using System;
using System.Collections.Generic;
using CodeCamp.Model;
namespace CodeCamp.Common.Utility
{
public class MockMessageService : IMessageServiceAsync
{
#region IMessageServiceAsync Members
public IAsyncResult BeginGetMessages(AsyncCallback callback,
object state)
{
return new MockAsyncResult { AsyncState = state };
}
public IList<Message> EndGetMessages(IAsyncResult result)
{
return new List<Message> {
new Message { Content = "Message 1",
Date = new DateTime(2009, 1, 1, 15, 02, 35) },
new Message { Content = "Message 2",
Date = new DateTime(2009, 1, 1, 15, 08, 21) },
new Message { Content = "Message 3",
Date = new DateTime(2009, 1, 1, 15, 11, 01) }
};
}
public IAsyncResult BeginAddMessage(Message message,
AsyncCallback callback, object state)
{
return new MockAsyncResult { AsyncState = state };
}
public void EndAddMessage(IAsyncResult result)
{
return;
}
#endregion
}
}
ServiceLocator.cs
using System;
using System.Diagnostics;
using CodeCamp.Common;
using CodeCamp.Common.Utility;
using CodeCamp.Common.ViewModel;
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Unity;
using CodeCamp.Model;
using CodeCamp.Common.Services;
namespace CodeCamp.History
{
public class ServiceLocator
{
private static IUnityContainer BuildDesignTimeContainer()
{
IUnityContainer container = new UnityContainer();
// register view models
container.RegisterType<IMessageServiceAsync, MockMessageService>();
return container;
}
private static IUnityContainer _container;
public static IUnityContainer Container
{
get
{
if (_container == null)
{
// setup container
_container = BuildDesignTimeContainer();
}
return _container;
}
set
{
_container = value;
}
}
#region ViewModels
public static HistoryViewModel HistoryViewModel
{
get
{
try
{
return Container.Resolve<HistoryViewModel >();
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
return null;
}
}
}
#endregion
}
}
HistoryView.xaml
<UserControl x:Class="CodeCamp.History.HistoryView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:History="clr-namespace:CodeCamp.History"
xmlns:Common="clr-namespace:CodeCamp.Common;assembly=CodeCamp.Common"
Width="400" Height="300">
<UserControl.Resources>
<History:ServiceLocator x:Key="HistoryService" />
<Common:DateFormatConverter x:Key="DateFormatter" />
</UserControl.Resources>
<ScrollViewer DataContext="{Binding Source={StaticResource HistoryService},
Path=HistoryViewModel}">
<ListBox ItemsSource="{Binding History}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
FontWeight="Bold"
Foreground="Green"
Text="{Binding Date,
Converter={StaticResource DateFormatter},
ConverterParameter=H:mm:ss tt}" />
<TextBlock