关于多个WCF 服务 1、如何在控制台中Host多个WCF服务?2、要是服务继承多个契约,在服务器配置文件中该如何写?PS:不能是多个Open方法,那样太幼稚了。谢谢! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 楼主的问题提的不错。我也最近在学习WCF相关内容,也希望能够与大家进行讨论。我大概说说我的感受,但不一定能够帮到你。我觉得WCF是一种通信机制,关键功能在于通信,因此,在处理对象关系方面,应该尽量将其置于其它层面,而不要在WCF的层面上做,这样就复杂了。比如你所说的服务继承多个契约,我认为,从WCF角度考虑,是应该需要避免的,我们是不是可以考虑,把这多个契约的功能合并一下。比如,在领域模型中,类与类之间的关系处理是非常频繁的事情,一个类可以继承于另一个类,并实现多个接口,这些都是合理的,因为他们遵循业务需求,是领域问题在计算机上的一种表现形式,那么在处理完这些业务逻辑后,我们需要通过某种机制将处理结果传输到UI,并显示给用户,那么这个传输工作就由WCF完成。事实上国外有很多文章都谈到至今WCF都不太流行的原因,大多都认为WCF在扩展性支持方面做的不是很好,即使有类似DynamicProxy的东西,也无法完美的解决WCF的扩展问题。设想,如果今后你的业务系统发生了更改,在服务端添加了某些服务契约,那么在客户端,你不得不去修改配置文件以达到使用这个服务的目的。退一步说,如果你的服务端公布的契约很多,那么你不得不去维护一个庞大的配置文件,这是让人头疼的事情。所以我觉得,WCF层面上的设计应该要尽量简单,不要将过多的逻辑放在这个层面。不知楼主是否能够苟同我的想法呢。 首先,服务的一些配置都在配置文件中,如下<?xml version="1.0" encoding="utf-8"?><configuration> <system.serviceModel> <services> <service name="ChinaQueue.Restaurant.WCFService.ServiceImplementations.PrinterSer" behaviorConfiguration="sb"> <host> <baseAddresses> <add baseAddress="net.tcp://localhost:8081" /> </baseAddresses> </host> <endpoint name="NetTcpBinding_IPrinterServer" address="PrinterSer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.IPrinterSer" /> <endpoint name="MexTcpBinding_IPrinterServer" address="Printer" binding="mexTcpBinding" contract="IMetadataExchange" /> </service> <service name="ChinaQueue.Restaurant.WCFService.ServiceImplementations.CounterSer" behaviorConfiguration="sb"> <host> <baseAddresses> <add baseAddress="net.tcp://localhost:8081" /> </baseAddresses> </host> <endpoint name="NetTcpBinding_ICounterServer" address="CounterSer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.ICounterSer" /> <endpoint name="MexTcpBinding_ICounterServer" address="Counter" binding="mexTcpBinding" contract="IMetadataExchange" /> </service> <service name="ChinaQueue.Restaurant.WCFService.ServiceImplementations.QuerySer" behaviorConfiguration="sb"> <host> <baseAddresses> <add baseAddress="net.tcp://localhost:8081" /> </baseAddresses> </host> <endpoint name="NetTcpBinding_IQueryServer" address="QuerySer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.IQuerySer" /> <endpoint name="MexTcpBinding_IQueryServer" address="Query" binding="mexTcpBinding" contract="IMetadataExchange" /> </service> </services> <behaviors> <serviceBehaviors> <behavior name="sb"> <serviceMetadata /> <serviceDebug includeExceptionDetailInFaults="true" /> </behavior> </serviceBehaviors> </behaviors> <bindings> <netTcpBinding> <binding name="NetTcpBinding_IServer"> <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" /> <security mode="None"> <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" /> <message clientCredentialType="Windows" /> </security> </binding> </netTcpBinding> </bindings> <client> <endpoint address="net.tcp://localhost:8081/PrinterSer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.IPrinterSer" name="NetTcpBinding_IPrinterServer" /> <endpoint address="net.tcp://localhost:8081/CounterSer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.ICounterSer" name="NetTcpBinding_ICounterServer" /> <endpoint address="net.tcp://localhost:8081/QuerySer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.IQuerySer" name="NetTcpBinding_IQueryServer" /> </client> </system.serviceModel></configuration>以上是三个服务的配置,然后在Main方法中Host这三个服务,以下是如何从配置文件中读取服务并进行Host的Configuration conf = ConfigurationManager.OpenExeConfiguration(Assembly.GetEntryAssembly().Location); ServiceModelSectionGroup svcmod = (ServiceModelSectionGroup)conf.GetSectionGroup("system.serviceModel"); foreach (ServiceElement el in svcmod.Services.Services) { Type svcType = Type.GetType(el.Name + "," + "ChinaQueue.Restaurant.WCFService"); if (svcType == null) throw new Exception("Invalid Service Type " + el.Name + " in configuration file."); aServiceHost = new ServiceHost(svcType); aServiceHost.Open(); }这是以前写过的一个多服务的项目中的代码,还有什么不明白的地方加QQ79878172 顶一下!楼上的代码完全可行,我也这样用过。但这种是多个serviceHost的Open调用,不知楼主是否满意。 首先很感谢二楼“飞雪孤风”的正确答案,但是学习过程中还是有小小的疑问:<?xml version="1.0" encoding="utf-8" ?><configuration> <system.serviceModel> <services> <service behaviorConfiguration="MyBehavior1" name="Book.Bll.UserBll"> <endpoint address="UserBll" binding="netTcpBinding" bindingConfiguration="DuplexBinding" contract="Book.Contract.IUser" /> <endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="net.tcp://localhost:9999/Service" /> </baseAddresses> </host> </service> <service behaviorConfiguration="MyBehavior2" name="Book.Bll.UserOperation"> <endpoint address="UserOperation" binding="netTcpBinding" bindingConfiguration="DuplexBinding" contract="Book.Contract.ICommonOperation" /> <endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="net.tcp://localhost:9999/Service" /> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior name="MyBehavior1"> <serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:9111/Service" /> <serviceThrottling maxConcurrentSessions="10000" /> <serviceDebug includeExceptionDetailInFaults="true"/> </behavior> <behavior name="MyBehavior2"> <serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:9112/Service" /> <serviceThrottling maxConcurrentSessions="10000" /> <serviceDebug includeExceptionDetailInFaults="true"/> </behavior> </serviceBehaviors> </behaviors> <bindings> <netTcpBinding> <binding name="DuplexBinding"> <reliableSession enabled="true" /> <security mode="None" /> </binding> </netTcpBinding> </bindings> </system.serviceModel></configuration>我的多服务配置文件这样写,其中<behavior name="MyBehavior1">和<behavior name="MyBehavior2">分别对应两个服务,不知道为什么会这样,如果只有一个<behavior>的话,两个服务都引用它,就会报错,好像二楼“飞雪孤风”也是这样引用的啊,怎么没事?还有直接把<client>节点写在服务器端配置文件里也行吗?再者我执行Type svcType = Type.GetType(el.Name+","+"Book");这句时,发那会的svcType=null,这怎么解决。 #sunnychen.org首先还是表示对这帖子的关注!O(∩_∩)O~目前对我来说合并契约也许是一个不错的选择。在WCF中,如果服务多了,庞大的配置文件和客户端代理类的却是一个令人头疼的问题,但是事情总是两面的,也好的就会有不好的。“WCF层面上的设计应该要尽量简单”这是应该遵循的,但是如果有的逻辑必需交给服务器处理,那就没有办法逃避了。 好长时间没弄WCF了,但是楼主,我写的服务配置是在本机上的8081端口上开了三个服务,就是说一个端口上有三个服务可访问,通讯方式是TCP传输.而你的配置是开了两个端口,一个是9111,一个是9112,而且behavior设置是HTTP传输的.但你设置服务的地址时是Net.Tcp啊,我不明白你为什么这样配置! #ycsno1这样就能够通过svcutil获取服务端的元数据了。如果按你那样写的话,怎么样通过svcutil工具获取元数据呢? 我在使用WCF过程中也遇到同样的问题,一开始准备构建N个服务接口,但是就光打开、关闭就N个,还有非常复杂的配置文件,维护起来比较麻烦。 http://xiaoyu8882008.blog.163.com/blog/static/1068919142010315414383/ 这里面这种方法完全可用,我试过了,只用改配置就可以了 C#如何实现外排序 请教高手解决!!!!!!!!C# Winfrom打印问题,急!!!!!!!! 这种功能如何实现? 读取文本文档的数据赋给变量 请问怎样让别的电脑运行C#编的应用程序? 要运行c#编的程序,需要安装哪些东西? .net2002升级到2003出现的问题? 请问:在应用程序中如何直接输出信息以控制台程序输出? sql server 数据库部署问题 各位高手,帮我看一下这是什么问题? C#中的数据绑定控件,能加入自定义的控件么 更新实体(edmx)时为何导致路径改变?
所以我觉得,WCF层面上的设计应该要尽量简单,不要将过多的逻辑放在这个层面。不知楼主是否能够苟同我的想法呢。
<configuration>
<system.serviceModel>
<services>
<service name="ChinaQueue.Restaurant.WCFService.ServiceImplementations.PrinterSer" behaviorConfiguration="sb">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8081" />
</baseAddresses>
</host>
<endpoint name="NetTcpBinding_IPrinterServer" address="PrinterSer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.IPrinterSer" />
<endpoint name="MexTcpBinding_IPrinterServer" address="Printer" binding="mexTcpBinding" contract="IMetadataExchange" />
</service>
<service name="ChinaQueue.Restaurant.WCFService.ServiceImplementations.CounterSer" behaviorConfiguration="sb">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8081" />
</baseAddresses>
</host>
<endpoint name="NetTcpBinding_ICounterServer" address="CounterSer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.ICounterSer" />
<endpoint name="MexTcpBinding_ICounterServer" address="Counter" binding="mexTcpBinding" contract="IMetadataExchange" />
</service>
<service name="ChinaQueue.Restaurant.WCFService.ServiceImplementations.QuerySer" behaviorConfiguration="sb">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8081" />
</baseAddresses>
</host>
<endpoint name="NetTcpBinding_IQueryServer" address="QuerySer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.IQuerySer" />
<endpoint name="MexTcpBinding_IQueryServer" address="Query" binding="mexTcpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="sb">
<serviceMetadata />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_IServer">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
<security mode="None">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://localhost:8081/PrinterSer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.IPrinterSer" name="NetTcpBinding_IPrinterServer" />
<endpoint address="net.tcp://localhost:8081/CounterSer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.ICounterSer" name="NetTcpBinding_ICounterServer" />
<endpoint address="net.tcp://localhost:8081/QuerySer" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IServer" contract="ChinaQueue.Restaurant.WCFService.ServiceContracts.IQuerySer" name="NetTcpBinding_IQueryServer" />
</client>
</system.serviceModel>
</configuration>以上是三个服务的配置,
然后在Main方法中Host这三个服务,以下是如何从配置文件中读取服务并进行Host的Configuration conf = ConfigurationManager.OpenExeConfiguration(Assembly.GetEntryAssembly().Location);
ServiceModelSectionGroup svcmod = (ServiceModelSectionGroup)conf.GetSectionGroup("system.serviceModel");
foreach (ServiceElement el in svcmod.Services.Services)
{
Type svcType = Type.GetType(el.Name + "," + "ChinaQueue.Restaurant.WCFService");
if (svcType == null)
throw new Exception("Invalid Service Type " + el.Name + " in configuration file.");
aServiceHost = new ServiceHost(svcType);
aServiceHost.Open();
}这是以前写过的一个多服务的项目中的代码,还有什么不明白的地方加QQ79878172
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service behaviorConfiguration="MyBehavior1" name="Book.Bll.UserBll">
<endpoint address="UserBll" binding="netTcpBinding" bindingConfiguration="DuplexBinding"
contract="Book.Contract.IUser" />
<endpoint address="mex" binding="mexTcpBinding" bindingConfiguration=""
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:9999/Service" />
</baseAddresses>
</host>
</service>
<service behaviorConfiguration="MyBehavior2" name="Book.Bll.UserOperation">
<endpoint address="UserOperation" binding="netTcpBinding" bindingConfiguration="DuplexBinding"
contract="Book.Contract.ICommonOperation" />
<endpoint address="mex" binding="mexTcpBinding" bindingConfiguration=""
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:9999/Service" />
</baseAddresses>
</host>
</service>
</services> <behaviors>
<serviceBehaviors>
<behavior name="MyBehavior1">
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:9111/Service" />
<serviceThrottling maxConcurrentSessions="10000" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
<behavior name="MyBehavior2">
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:9112/Service" />
<serviceThrottling maxConcurrentSessions="10000" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors> <bindings>
<netTcpBinding>
<binding name="DuplexBinding">
<reliableSession enabled="true" />
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
</configuration>我的多服务配置文件这样写,其中<behavior name="MyBehavior1">和<behavior name="MyBehavior2">分别对应两个服务,不知道为什么会这样,如果只有一个<behavior>的话,两个服务都引用它,就会报错,好像二楼“飞雪孤风”也是这样引用的啊,怎么没事?
还有直接把<client>节点写在服务器端配置文件里也行吗?
再者我执行Type svcType = Type.GetType(el.Name+","+"Book");这句时,发那会的svcType=null,这怎么解决。
首先还是表示对这帖子的关注!O(∩_∩)O~
目前对我来说合并契约也许是一个不错的选择。在WCF中,如果服务多了,庞大的配置文件和客户端代理类的却是一个令人头疼的问题,但是事情总是两面的,也好的就会有不好的。
“WCF层面上的设计应该要尽量简单”这是应该遵循的,但是如果有的逻辑必需交给服务器处理,那就没有办法逃避了。
这样就能够通过svcutil获取服务端的元数据了。
如果按你那样写的话,怎么样通过svcutil工具获取元数据呢?