ObservableServiceHost – An InstanceContext creation aware WCF ServiceHost
Posted by Dan Rigsby on August 20th, 2008
ServiceHost host = new ServiceHost(typeof(MyService)); host.Open(); host.InstanceCreated += new EventHandler<InstanceEventArgs>(host_InstanceCreated);
- PerCall: Every call made to the endpoints would create a new service instance. This could be useful.
- PerSession: Every new client connection would create a new service instance for the life of the client’s session. This could be very useful.
- Single: A service instance is created during the first call. This is fairly useless since it is called when the single instance of the service starts, but not again.
However, I accepted the challenge to come up with an implementation of this extension. What I came up with is called ObservableServiceHost. This is a custom ServiceHost that you can use instead of the default System.ServiceModel.ServiceHost. The solution requires only 4 files:
1. InstanceEventArgs
A simple EventArgs class is needed as a container for the InstanceContext.
public class InstanceEventArgs : EventArgs { public InstanceContext InstanceContext { get; set; } public InstanceEventArgs() { } public InstanceEventArgs( InstanceContext instanceContext) { InstanceContext = instanceContext; } }
2. ObservableServiceHost
ObservableServiceHost extends the functionality of a ServiceHost. This class consists of the following:
- A new event called InstanceCreated which uses the InstanceEventArgs.
- Re-implemented constructors of the base ServiceHost class.
- When the ServiceHost is Opened, a custom IEndpointBehavior is added to each of the endpoints used at the time the service is opened. Endpoints which implement IMetadataExchange are be ignored though since the event doesn’t need to be fired a new metadata instance is created. (You could potentially modify this to add a different behaviors for different service interfaces.)
public class ObservableServiceHost : ServiceHost { public event EventHandler<InstanceEventArgs> InstanceCreated; protected internal virtual void OnInstanceCreated( InstanceContext instanceContext) { EventHandler<InstanceEventArgs> handler = InstanceCreated; if (handler != null) { handler(this, new InstanceEventArgs(instanceContext)); } } public ObservableServiceHost( object singletonInstance, params Uri[] baseAddresses) : base(singletonInstance, baseAddresses) { } public ObservableServiceHost( Type serviceType, params Uri[] baseAddresses) : base(serviceType, baseAddresses) { } protected override void OnOpening() { AddInstanceContextInitializers(); base.OnOpening(); } private void AddInstanceContextInitializers() { foreach (ServiceEndpoint endpoint in this.Description.Endpoints) { if (endpoint.Contract.ContractType != typeof(IMetadataExchange)) { endpoint.Behaviors.Add(new InstanceCreationEndpointBehavior(this)); } } } }
3. InstanceCreationInitializer
This is a basic implementation of IInstanceContextInitializer which can be used to inspect the InstanceContext when an instance is created. This class consists of the following:
- A constructor that takes in a reference to the ObservableServiceHost.
- An implementation of IInstanceContextInitializer.Initialize which fires the InstanceCreated event on the referenced ObservableServiceHost when the InstanceContext is created.
public class InstanceCreationInitializer : IInstanceContextInitializer { private ObservableServiceHost m_ObservableServiceHost; #region IInstanceContextInitializer Members public void Initialize( InstanceContext instanceContext, Message message) { if (m_ObservableServiceHost != null) { m_ObservableServiceHost.OnInstanceCreated(instanceContext); } } #endregion IInstanceContextInitializer Member public InstanceCreationInitializer( ObservableServiceHost observableServiceHost) { m_ObservableServiceHost = observableServiceHost; } }
4. InstanceCreationEndpointBehavior
This class implements IEndpointBehavior which is used to extend the runtime behavior of an endpoint and add our InstanceCreationInitializer to the endpoint dispatcher. It is this behavior that we add to each of the endpoints when the ObservableServiceHost opens.
This class consists of the following:
- A constructor that takes in a reference to the ObservableServiceHost and creates an instance of the InstanceCreationInitializer.
- An implementation of IEndpointBehavior.ApplyDispatchBehavior which adds our InstanceCreationInitializer to the endpoint dispatchers InstanceContextInitializers collection. This will cause our InstanceCreationInitializer to be run when a new instance is created. The InstanceCreationInitializer in turn calls our InstanceCreated event on the ObservableServiceHost.
public class InstanceCreationEndpointBehavior : IEndpointBehavior { private InstanceCreationInitializer m_InstanceCreationInitializer; #region IEndpointBehavior Members public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { endpointDispatcher.DispatchRuntime.InstanceContextInitializers.Add( m_InstanceCreationInitializer); } public void Validate(ServiceEndpoint endpoint) { } #endregion IEndpointBehavior Members public InstanceCreationEndpointBehavior( ObservableServiceHost observableServiceHost) { m_InstanceCreationInitializer = new InstanceCreationInitializer(observableServiceHost); } }
Example Service
Included in the code for this article is an example of how to use this library. You can take any new or existing service and use it with the ObservableServiceHost, then just attach to the InstanceCreated event:
static class Program { static void Main(string[] args) { ObservableServiceHost serviceHost = new ObservableServiceHost( typeof(MyService)); serviceHost.Open(); serviceHost.InstanceCreated += new EventHandler<InstanceEventArgs>(serviceHost_InstanceCreated); Console.WriteLine("Press any key to exit application..."); Console.WriteLine(); Console.ReadLine(); serviceHost.Close(); } static void serviceHost_InstanceCreated(object sender, InstanceEventArgs e) { Console.WriteLine("New InstanceContext created"); } }

You can play around with the InstanceContextMode on the Service to see what happens when you use it with PerCall, PerSession, or Single. The line of code to look for is:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
I hope others find this class useful or at least have learned more about the extensibility that WCF has to offer. You can download the complete library and sample server here: http://www.danrigsby.com/Files/Rigsby.ServiceHostCreation.zip


















August 21st, 2008 at 9:10 am
[...] ObservableServiceHost - An InstanceContext Creation-Aware WCF ServiceHost (Dan Rigsby) [...]
September 19th, 2008 at 3:44 pm
Good job. This is very useful and used aspect wcf for me
September 21st, 2008 at 3:08 pm
[...] We have looked at a couple of the extensions points on this blog in the past (ObservableServiceHost & Extending InstanceContext). Another extension point is an IContextChannel Extension. This [...]