如何为没有SVC文件的自托管WCF服务指定ServiceHostFactory

我的应用程序作为Windows服务运行。 它使用以下帮助器方法动态创建WCF服务:

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); } } 

这些服务没有.SVC文件。 还要明确的是,这些是自托管服务,不在IIS下运行 – 它们在WAS(Windows激活服务)下运行。

现在我想控制实现类的实例化方式。 听起来这可以通过ServiceHostFactory来完成。 但是我发现所有关于这个的文章都说,指定使用什么工厂的方法是将类型名称放在.SVC文件的@ServiceHost指令中。 我没有这个档案!

有没有办法在WAS下运行没有SVC文件的WCF服务使用我自己的ServiceHost工厂?

更新以下答案

这是我的新辅助方法,结合了Carlos的解决方案

  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 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) { } } 

您不需要服务主机工厂来控制如何实例化服务实现类 – 您需要通过使用自定义服务行为将IInstanceProvider添加到调度运行时。 http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/31/wcf-extensibility-iinstanceprovider.aspx上的博客文章详细介绍了如何实现这一目标。 例如,下面的SSCCE显示了如何使用实例提供程序的示例(对于没有默认构造函数的服务,因此在WCF中不能直接使用,没有实例提供程序)

 public class StackOverflow_29825519 { [ServiceContract] public interface ITest { [OperationContract] string WhoAmI(); } public class Service : ITest { string name; public Service(string name) { this.name = name; } public string WhoAmI() { return this.name; } } class MyBehavior : IServiceBehavior, IInstanceProvider { 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) { 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 new Service("John Doe"); } public void ReleaseInstance(InstanceContext instanceContext, object instance) { } } public static void Test() { string baseAddress = "http://" + Environment.MachineName + ":8000/Service"; ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress)); host.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), ""); host.Description.Behaviors.Add(new MyBehavior()); host.Open(); Console.WriteLine("Host opened"); ChannelFactory factory = new ChannelFactory(new BasicHttpBinding(), new EndpointAddress(baseAddress)); ITest proxy = factory.CreateChannel(); Console.WriteLine("WhoAmI: {0}", proxy.WhoAmI()); ((IClientChannel)proxy).Close(); factory.Close(); Console.Write("Press ENTER to close the host"); Console.ReadLine(); host.Close(); } }