My application runs as a Windows service. It dynamically creates WCF services using the following helper method:
public static void StartWebService(string webServiceName, Type serviceContractType, Type serviceImplementationType)
{
if (string.IsNullOrEmpty(webServiceName)) return;
var baseAddress = GetWebServiceAddress(webServiceName);
var baseUri = new Uri(baseAddress);
lock (RunningWebServices)
{
if (RunningWebServices.ContainsKey(webServiceName))
return;
var webServiceHost = new ServiceHost(serviceImplementationType, baseUri);
var serviceBehaviour = new ServiceMetadataBehavior() { HttpGetEnabled = true };
webServiceHost.Description.Behaviors.Add(serviceBehaviour);
webServiceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
var httpBinding = new BasicHttpBinding();
webServiceHost.AddServiceEndpoint(serviceContractType, httpBinding, baseAddress);
webServiceHost.Open();
RunningWebServices.Add(webServiceName, webServiceHost);
}
}
There is no .SVC file for these services. Also be clear that these are self-hosted services, not running under IIS - they are running under WAS (Windows Activation Services).
Now I want to control how the implementation class is instantiated. It sounds like this can be done with a ServiceHostFactory. However all the articles about this I have found say that the way to specify what factory to used is to put the type name in the @ServiceHost directive of the .SVC file. I don't have this file!
Is there any way to use my own ServiceHost factory for WCF services with no SVC file running under WAS?
Update following answer
Here is my new helper method incorporating Carlos' solution
public static void StartWebService(string webServiceName, Type serviceContractType, Type serviceImplementationType)
{
if (string.IsNullOrEmpty(webServiceName)) return;
var baseAddress = GetWebServiceAddress(webServiceName);
var baseUri = new Uri(baseAddress);
lock (RunningWebServices)
{
if (RunningWebServices.ContainsKey(webServiceName))
return;
var webServiceHost = new ServiceHost(serviceImplementationType, baseUri);
webServiceHost.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = true });
webServiceHost.Description.Behaviors.Add(new CustomWebServiceBehavior());
webServiceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
webServiceHost.AddServiceEndpoint(serviceContractType, new BasicHttpBinding(), baseAddress);
webServiceHost.Open();
RunningWebServices.Add(webServiceName, webServiceHost);
}
}
internal class CustomWebServiceBehavior : IServiceBehavior, IInstanceProvider
{
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHost)
{
foreach (ChannelDispatcher cd in serviceHost.ChannelDispatchers)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.InstanceProvider = this;
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
return this.GetInstance(instanceContext);
}
public object GetInstance(InstanceContext instanceContext)
{
return // this is where I use my factory;
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
}
}