inheritanceWCF中的通用契约

更多WCF问题…… 🙂

我的所有工作流程都实现了相同的3种方法。 经过大量的复制和粘贴后,我决定让它们从同一个界面inheritance:

[ServiceContract(Namespace = "http://schema.company.com/messages/")] public interface IBasicContract where TRequest : class where TResponse : class { [OperationContract(Name = "GetReport", Action = "http://schema.company.com/messages/GetReport", ReplyAction = "http://schema.company.com/messages/GetReportResponse")] TResponse GetReport(TRequest inquiry); [OperationContract(Name = "GetRawReport", Action = "http://schema.company.com/messages/GetRawReport", ReplyAction = "http://schema.company.com/messages/GetRawReportResponse")] string GetRawReport(string guid); [OperationContract(Name = "GetArchiveReport", Action = "http://schema.company.com/messages/GetArchiveReport", ReplyAction = "http://schema.company.com/messages/GetArchiveReportResponse")] TResponse GetArchiveReport(string guid); } 

我还决定创建服务客户端的通用实现:

 public class BasicSvcClient : ClientBase<IBasicContract>, IBasicContract where TRequest : class where TResponse : class { public BasicSvcClient() { } public BasicSvcClient(string endpointConfigurationName) : base(endpointConfigurationName) { } public BasicSvcClient(string endpointConfigurationName, string remoteAddress) : base(endpointConfigurationName, remoteAddress) { } public BasicSvcClient(string endpointConfigurationName, EndpointAddress remoteAddress) : base(endpointConfigurationName, remoteAddress) { } public BasicSvcClient(Binding binding, EndpointAddress remoteAddress) : base(binding, remoteAddress) { } public TResponse GetReport(TRequest inquiry) { return Channel.GetReport(inquiry); } public string GetRawReport(string guid) { return Channel.GetRawReport(guid); } public TResponse GetArchiveReport(string guid) { return Channel.GetArchiveReport(guid); } } 

问题是当我尝试使用它时:

 using (var client = new BasicSvcClient()) { var response = client.GetReport(inquiry); context.Response.ContentType = "text/xml"; context.Response.Write(response.AsXML()); } 

我总是收到一个错误,说它无法找到合同IBasicContract的配置,因为.NET使用了这种奇怪的语法:

找不到引用契约’BasicWorkflow.IBasicContract`2的默认端点元素…

我试过这样做:

 using (var client = new BasicSvcClient("myConfig")) 

它没有帮助 – 它仍然在寻找特定的合同。

我知道ServiceContract属性有一个ConfigurationName参数,但我不能在编译时使用它,因为我有很多工作流程,我从同一个程序调用(因此有很多配置条目)。 有没有办法在运行时设置ConfigurationName? 我认为这是ClientBase构造函数应该做的,但显然不是。

[编辑]这是.config文件中的端点,我不相信它在这种情况下非常有用:

  

[编辑2]好的……我发现了一种有效的方法,尽管我仍然不满意它:

 using (var wf = new BasicSvcClient( new BasicHttpBinding("httpsDataEndpoint"), new EndpointAddress("https://localhost/services/Contract.svc"))) 

我现在唯一的问题是我更愿意从.config文件中检索端点地址(使用实际的合同名称,如IContract)。 有谁可以帮我这个部分?

[Edit3]终于找到了完整的解决方案:)万岁reflection器!

 var cf = (ClientSection) ConfigurationManager.GetSection("system.serviceModel/client"); foreach (ChannelEndpointElement endpoint in cf.Endpoints) { if (endpoint.Name != "ContractSvc") continue; using (var wf = new BasicSvcClient( new BasicHttpBinding("httpsDataEndpoint"), new EndpointAddress(endpoint.Address.ToString()))) { //... call wf.GetReport() } break; } 

“.NET使用的奇怪语法”实际上是绑定到特定类型的generics类型在运行时的类型名称。 Typename`n [[Type],…]其中n表示generics类型中包含的类型参数的数量。

您的端点配置如何?

为什么不在ServiceContract属性中指定合同的名称:

 [ ServiceContract ( Namespace = "http://schema.company.com/messages/", Name="MyBasicContract" ) ] 

如果您没有明确指定名称,则默认使用“.NET使用的奇怪语法”中接口的限定名称。

如果要使用IBasicContract等服务契约,则必须使用在配置文件中定义generics类型的标准方法

它写在配置文件中,如下所示:IBasicContract`2 [TRequest,TResponse]

当你发布他们的问题时,我也在我的博客(www.lybecker.com/blog/)上回复了。

🙂 Anders Lybecker