Friday, 20 April 2018

wcf instance provider

Ever tried applying dependency injection container concepts in a WCF service? Well, you might say that not many people use WCF these days as majority of services are moving towards REST WebAPI. While that is true, it is also true that WCF gives us features and capabilities that a REST WebAPI has no support of. Anyhow, there is not much value to fight the urge to write a good WCF service with a decent DI logic.

All you have to do is to write an implementation of IInstanceProvider and apply a custom implementation of IServiceBehavior to the service.

IServiceBehavior:

public class CustomInstanceProviderBehaviorAttribute : Attribute, IServiceBehavior
    {
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection endpoints, BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
            {
                foreach (EndpointDispatcher ed in cd.Endpoints)
                {
                    if (!ed.IsSystemEndpoint)
                    {
                        ed.DispatchRuntime.InstanceProvider = new DIInstanceProvider(DateTime.UtcNow.Ticks);
                    }
                }
            }
        }

        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
        }

    }

IInstanceProvider

public class DIInstanceProvider : IInstanceProvider
    {
        private long ticks = 0L;

        public DIInstanceProvider(long ticksValue)
        {
            this.ticks = ticksValue;
        }

        public object GetInstance(InstanceContext instanceContext)
        {
            return new Service1(DateTime.UtcNow.Ticks);
        }

        public object GetInstance(InstanceContext instanceContext, Message message)
        {
            return new Service1(DateTime.UtcNow.Ticks);
        }

        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
        }

    }

Service
    [CustomInstanceProviderBehavior]
    public class Service1 : IService1
    {
        private long ticks = 0L;

        public Service1(long ticks)
        {
            this.ticks = ticks;
        }

        public string GetData(int value)
        {
            return string.Format("You entered: {0} at {1}", value, this.ticks);

        }
     }

Point to note: Instance of IInstanceProvider is created only once when service starts and applies the service behavior. However the service instance is created by calling GetInstance method of IInstanceProvider.

No comments:

Post a Comment