Integrating silverlight 3 polling duplex with unity container
These days everybody are using IOC container so I tried to integrate SL 3 Beta(MIX09) Sample chat application that represent how to work with polling duplex with Unity Ioc container. That sample chat application is available for download on codeplex.
After looking how to integrate Unity with Wcf I have founded few nice examples. All those examples are pretty much same.
To integrate Unity with Wcf we must create UnityServiceHostFactory and in markup of service say that service use that factory.
Polling duplex however has also DuplexServiceFactory. So how I integrate those two factories?
I have created all classes needed for UnityServiceHostFactory in UnityServiceHostFactory.cs file such as UnityServiceHost, UnityInstanceProvider and UnityServiceBehavior.
To make example more interesting I have also create IExample interface to inject this interface in service contructor like this:
public ChatService(IExample example)
{
examp = example;
//Set up a stock update every 5 seconds
this.stockTimer = new Timer(
new TimerCallback(StockUpdate),
null, 0, 5000);
}
void StockUpdate(object o)
{
StockTickerMessage stm = new StockTickerMessage();
//change this message to use method in interface
stm.stock = “MSFT”;
stm.stock += examp.GetMessage();//calling method from injected interface
stm.price = new System.Random().Next(20, 50);
PushToAllClients(stm);
}
In StockUpdate method in ChatService class in have called method GetMessage from Example class:
class Example : IExample
{
public string GetMessage()
{
return “Example”;
}
}
In DuplexServiceFactory I have changed CreateServiceHost to use Unity container.
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
UnityServiceHost host = new UnityServiceHost(serviceType, baseAddresses);
UnityContainer unity = new UnityContainer();
host.Container = unity;
unity.RegisterType<IExample, Example>();
CustomBinding binding = new CustomBinding(
new PollingDuplexBindingElement(),
new BinaryMessageEncodingBindingElement(),
new HttpTransportBindingElement());
host.Description.Behaviors.Add(new ServiceMetadataBehavior());
host.AddServiceEndpoint(typeof(IUniversalDuplexContract), binding, “”);
host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), “mex”);
return host;
}
Now if I run my sample application I get error:
“The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor. To fix the problem, add a default constructor to the type, or pass an instance of the type to the host.”
Reason for this is because my Polling duplex class is decorated as singleton class
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public abstract class DuplexService : IUniversalDuplexContract
{
and ServiceDescription.CreateImplementation and is hard-coded to look for a parameterless constructor.
But I want to make contructor injection so my service class must have contructor with parameter.
I have been remove [ServiceBehavior(InstanceContextMode=InstanceContextMode.SIngle)] and let Unity to return singleton instance of DuplexService class.
So I have put in web config file some code that Unity will use to return Singleton instance of DuplexService.
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" /> <unity> <containers> <container> <types> <type type="Microsoft.Silverlight.Cdf.Samples.Duplex.IUniversalDuplexContract,ChatWebApp" mapTo="Microsoft.Silverlight.Cdf.Samples.Chat.ChatService,ChatWebApp" > <lifetime type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity" /> </type> </types> </container> </containers> </unity>
After that I have consumed code from web config in my application.
UnityServiceHost host = new UnityServiceHost(serviceType, baseAddresses);
UnityContainer unity = new UnityContainer();
host.Container = unity;
unity.RegisterType<IExample, Example>();
UnityConfigurationSection section;
section = (UnityConfigurationSection)ConfigurationManager.GetSection(“unity”);
section.Containers.Default.Configure(unity);
I have tested this by calling IUniversalDuplexContract cont1 = unity.Resolve<IUniversalDuplexContract>() twice and comparing hash of two instances.
Hash was exactly same.That means that Unity returns singleton instance of ChatService class.
I hope this will help.
Demo project : DuplexWithUnity