Sunday, September 6, 2009

NO MORE BLOGGER

Greetings

I am now using WORDPRESS for my hamletcode blogging activity.

Both of you, please update you RSS READERS to

http://hamletcode.wordpress.com

Thank you!

Code Test

 

I’m switching to Wordpress.

Trying a code sample….

 

   1: namespace YaddaYadda



   2: {



   3:     public class Whatever



   4:     {



   5:         public void DoSomething()



   6:         {



   7:         }



   8:     }



   9: }


Wednesday, September 2, 2009

So what’s the deal with the thread blocking in vs2010/.net4?

This was weird. I didn’t say anything in last night’s post because I wanted to make sure I wasn’t insane. I’m pretty sure I’m not.

Anyhoo, I created a stupid little windows form application to host my Wcf Service and to also to create a client.

The PAGE_LOAD calls a StartServer() method, which creates the service host.

The form has a TEST button that creates a WCF client to the same service.

That’s all pretty common stuff; start a server, create a client. But, the client kept reporting a Wcf timeout after 1 minute. I was able to connect to the service from another process, but not from within the windows form. It seemed like maybe a threading issue.

So, I changed the client to run in another thread, and it worked. Why’s that?

Injecting into a Wcf Service

 

Update 9/2/2009: I forgot to include the service contract. Added it.

Overview

When you setup a Service Host, WCF manages the creation of your services. It requires there to be a default constructor so that it can just instantiate the thing and be done with it.

I often find myself wishing to be able to pass something into the object when its created. For example: a unity container. I’d like to inject the unity container.

Lacking that ability, we end up with a static container somewhere that the service calls.

public class TestService : ITestService
{
    public void DoSomething() 
    {
        IWhatever whatever = StaticHelper.Container.Resolve<IWhatever>();
    }
}








What’s wrong with that? Statics are evil. Whenever you use a static, there should be a big red flag. Sure, its convenient, but its not very testable or flexible.









Sometime we can somewhat counter the testability limitation as follows









public class TestService : ITestService
{
    private readonly IUnityContainer _unityContainer;
    public TestService() 
    {
        // wcf will use this constructor
        _unityContainer = StaticHelper.Container;
    }
    // tests use this constructor
    public TestService(IUnityContainer container) 
    {
        _unityContainer = container;
    }  
    public void DoSomething() 
    {
        IWhatever whatever = _unityContainer.Resolve<IWhatever>();
    }
}








That works, but still smells kind of funny.









Tonight’s adventure was to figure out how to pass a unity container to the test service when instantiated. I didn’t really know where to start on this, so started at the ServiceHost, and googled the night away.









There are a bunch of examples out there to use unity to determine the implementation type of the service. Two examples that I looked at rely on a static IOC container in order to determine the implementation type. In those cases, the statics can be easily eliminated just by passing the container through the layers as I do here. (Their goal’s were different. My goal is to get rid of the statics.)









UPDATE: Now that I’ve gotten it all to work, and I’ve spent some time thinking about the conclusion, the fore mentioned approach is the best way. Rather than pulling objects from unity and assign it to properties, just define the service itself in the container. Then unity can handle all of the injection. I had to write this blog to come to that conclusion, so I’m not going to throw it all away.









Basic Steps













  1. Create a service host






  2. Create a behavior






  3. Create an instance provider – this is what we’re really interested in. This creates the service object. We need to get the IUnityContainer to this guy.






  4. Connect the host to the behavior






  5. Connect the behavior to the instance provider










I created a subclass of ServiceHost and added an IUnityContainer parameter to both of the constructors. The parameter value is saved to a local variable.









The service behavior has no knowledge of the IUnityContainer. It just gives us the bridge between the instance provider.









The instance provider has access to the service host. As you may recall, the service host has the IUnityContainer property. If the service object (implementation) has a IUnityContainer property, then we assign it.









The Code









DISCLAIMER: This code is just enough to get it to work. Its not tied up nice and neat.









An Interface for Services that require an IUnityContainer









The instance provider, way down at the bottom, will see if the service implements this interface. If so, it assigns the property.









namespace AllardWorks.AwBus.Contracts
{
    public interface IUnityWcfService
    {
        IUnityContainer UnityContainer { get; set; }
    }
}








The Service Host









    public class AwBusServiceHost : ServiceHost
    {
        public AwBusServiceHost(IUnityContainer container)
            : base()
        {
            _container = container;
        }
        public AwBusServiceHost(IUnityContainer container, Type serviceType, params Uri[] baseAddresses)
            : base(serviceType, baseAddresses)
        {
            _container = container;
        }
        protected override void OnOpening()
        {
            Description.Behaviors.Add(new AwBusServiceBehavior());
            base.OnOpening();
        }
        public readonly IUnityContainer _container;
        public IUnityContainer UnityContainer
        {
            get { return _container; }
        }
    }








The Behavior









We’re only interested in the ApplyDispatchBehavior method.









This loops through all of the endpoint dispatchers and sets the instance provider to one of our own design. We pass it the type that is to be instantiated.









    public class AwBusServiceBehavior : IServiceBehavior
    {
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
            {
                ChannelDispatcher cd = cdb as ChannelDispatcher;
                if (cd == null)
                {
                    continue;
                }
                foreach (EndpointDispatcher ed in cd.Endpoints)
                {
                    ed.DispatchRuntime.InstanceProvider = new AwBusInstanceProvider(serviceDescription.ServiceType);
                }
            }
        }
        #region Not Used
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
        }
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }
        #endregion
    }








The Instance Provider









At last, we get to create an object. Yay.









The interesting part here is the IUnityWcfService. If the new object implements that interface, then we set the UnityContainer property that the interface provides.









    public class AwBusInstanceProvider : IInstanceProvider
    {
        private readonly Type _type;
        public AwBusInstanceProvider(Type type)
        {
            _type = type;
        }
        public object GetInstance(InstanceContext instanceContext)
        {
            return GetInstance(instanceContext, null);
        }
        public object GetInstance(InstanceContext instanceContext, System.ServiceModel.Channels.Message message)
        {
            object service = Activator.CreateInstance(_type);
            IUnityWcfService unityService = service as IUnityWcfService;
            if (unityService != null)
            {
                unityService.UnityContainer = ((AwBusServiceHost)instanceContext.Host).UnityContainer;
            }
            return service;
        }
        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
        }
    }








Take it for a Test Drive



A Test Service. (Hand coded on the spot. Should be mostly correct though)



[ServiceContract]

public interface IDoSomething



{




[OperationContract]



bool HasContainer();




}



 



public class DoSomething : IDoSomething, IUnityWcfService{




public IUnityContainer UnityContainer { get; set; }



public bool HasContainer()



{



return UnityContainer != null;



}




}






The Server









        private IUnityContainer _unity;
        private ServiceHost _host;
        private void StartServer()
        {
            _unity = new UnityContainer();
            _host = new AwBusServiceHost(_unity, typeof(TestService), new Uri[] { });
            #region Mex
            BindingElement mexBindingElement = new TcpTransportBindingElement();
            CustomBinding mexBinding = new CustomBinding(mexBindingElement);
            ServiceMetadataBehavior metadataBehavior = _host.Description.Behaviors.Find<ServiceMetadataBehavior>();
            if (metadataBehavior == null)
            {
                metadataBehavior = new ServiceMetadataBehavior();
                _host.Description.Behaviors.Add(metadataBehavior);
            }
            _host.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, ServiceUri + "/MEX");
            #endregion

 

            #region NetTcp Endpoint
            c.Binding binding = new NetTcpBinding(SecurityMode.None);
            _host.AddServiceEndpoint(typeof(ITestService), binding, new Uri(ServiceUri));
            #endregion
            _host.Open();
        }








The Client









                c.Binding binding = new NetTcpBinding(SecurityMode.None);
                EndpointAddress address = new EndpointAddress(ServiceUri);
                using (ChannelFactory<ITestService> client = new ChannelFactory<ITestService>(binding, address))
                {
                    ITestService proxy = client.CreateChannel();
                    MessageBox.Show(proxy.HasContainer().ToString());
                }








Conclusion









This is pretty neat. This solves an inconvenience we’ve had at work, though at work we need a different object. We have this thing we call “the factory”, which is our own IOC container. We wrote it before unity was released and before we realized that it already a name (IOC).









Once you understand that you can pass anything you want to the service host, and then eventually pass it down to the service object, there are a lot of other injection possibilities. Maybe rather than pass the entire container to the service, you just pull out the objects the service needs an inject them. There are a few ways to do that, but after a few seconds of thought, I think that using unity to construct the service object itself is the best idea. (I found a few examples of this, so its an established approach.)