我通过IIS公开的同一个类实现了大量的服务合同,使用简化的配置(即配置文件中没有明确的<service>
个节点。)
这很好用并且给我们带来了很多麻烦,因为我们的客户端有一些逻辑可以自动构建指向同一个URL的端点。
现在,我想在客户端和服务器上自定义一个合同,因为它的行为与其他合同完全不同。我想为这个特殊的契约类使用流式传输,因为它返回并获取Stream
个实例。
一旦我尝试在服务器上添加<service>
节点,指向共享实现类并使用此特殊合同接口,其他服务的整个自动配置就会丢失,我就离开了暴露一个服务。我认为这与我使用单个实现类的事实有关,并且一旦Wcf检测到配置中存在具有该类名的服务,它就会停止自动生成其他合同的端点。
有没有办法让这项工作,仍然共享同一个类并保持简化的配置?
答案 0 :(得分:1)
您可以通过创建自己的服务工厂并覆盖部分激活过程来完成此操作。
假设您有两个这样的服务合同。
public interface IService1
{
[OperationContract]
string GetData(int value);
}
[ServiceContract]
public interface IService2
{
[OperationContract]
string Foobar();
}
假设这些是在像这样的单个类中实现的。
public class Service1 : IService1, IService2
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public string Foobar()
{
return "foobar";
}
}
现在,如果您只想更改第二个服务合同的端点,那么在.svc文件中,添加Factory属性以指向自定义服务工厂实现。
<%@ ServiceHost Language="C#" Debug="true" Factory="SimpleWCF2.MyServiceFactory" Service="SimpleWCF2.Service1" CodeBehind="Service1.svc.cs" %>
接下来,创建一个实例化自定义服务主机的自定义服务工厂。在自定义服务主机中,覆盖ApplyConfiguration并删除合同2的默认端点,并将其替换为自定义端点配置。例如,这里我只用合约2替换默认的“basicHttpBinding”和“WsHttpBinding”。你当然可以根据需要配置绑定(你提到了流媒体) - 这只是一个例子。
public class MyServiceFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new MyServiceHost(serviceType, baseAddresses);
}
}
public class MyServiceHost : ServiceHost
{
public MyServiceHost(Type serviceType, params Uri[] baseAddresses) :
base (serviceType, baseAddresses)
{ }
protected override void ApplyConfiguration()
{
base.ApplyConfiguration();
AddDefaultEndpoints();
// Remove the default endpoint for IService2
var defaultEp = this.Description.Endpoints.FirstOrDefault(e => e.Contract.ContractType == typeof(IService2));
this.Description.Endpoints.Remove(defaultEp);
// Add a new custom endpoint for IService2
this.AddServiceEndpoint(typeof(IService2), new WSHttpBinding(), "test");
}
}
就是这样。您的简化配置无需更改。
现在,您的客户将通过新的服务端点发现第二个合同。例如,这是我的样本中的WCF测试客户端。