代码改变世界

WCF 的几个问题

2011-08-02 13:02  DanielWise  阅读(2058)  评论(0编辑  收藏  举报

1. ChannelFactory.Endpoint.Address.Uri.AbsolutePath

需求: 如果我想通过endpointConfigurationName 来获取终结点信息,同时又想在运行时动态设定相对地址,应该怎么做?

1). 按照如下配置设置终结点信息,注意address 中的地址是编译时的地址,不是运行时的地址。

   1: <endpoint name="JobResultService"
   2:           address="http://0.0.0.0:0/JobResultService"
   3:           binding="basicBinding"
   4:           contract="http://danielWise.com.IJobResultContract"/>

2). 获得终结点信息

   1: ChannelFactory<IJobResultContract> channelFactory = 
   2:     new ChannelFactory<IJobResultContract>("JobResultService");

3). 生成运行时地址

   1: UriBuilder uriBuilder = new UriBuilder();
   2: uriBuilder.Scheme = "http";
   3: uriBuilder.Host = "127.0.0.1";
   4: uriBuilder.Port = 1234;
   5: //AbsolutePath == "/JobResultService";
   6: uriBuilder.Path = channelFactory.Endpoint.Address.Uri.AbsolutePath;

4). 设置运行时终结点地址

   1: channelFactory.Endpoint.Address = 
   2:     new EndpointAddress(uriBuilder.Uri.ToString());

这样你就可以通过App.config 中的终结点配置信息动态地修改运行时终结点地址,极大地方便了我们的使用。

2. 为Enum 使用[Flags]标识

需求:如果想获取多个枚举值的超集,请使用下面示例

   1: [DataContract]
   2: [Flags]
   3: public enum CarFeatures
   4: {
   5:     None = 0,
   6:     [EnumMember]
   7:     AirConditioner = 1,
   8:     [EnumMember]
   9:     AutomaticTransmission = 2,
  10:     [EnumMember]
  11:     PowerDoors = 4,
  12:     AlloyWheels = AutomaticTransmission | PowerDoors,
  13:     [NonSerialized]
  14:     CDPlayer = 8,
  15: }

限制:

1) 必须有[Flags]标签

2)所有应用了EnumMemberAttribute的枚举成员值必须是不间断的2的幂 (如 1, 2, 4, 8, 16, 32, 64).

3)如果通过数值来找枚举成员(比如通过4 来找PowerDoors),会先判断是否存在这个成员,不存在则判断是否存在这样的组合成员,如果仍然不存在且数值不为0的话则会抛出SerializationException,如果数值为0则返回空列表。

3. OperationContractAttribute.IsOneWay

默认情况下IsOneWay == false, 这种情况下即使方法返回空值(void)底层消息层也是双向通信,WCF架构会创建一条空消息并把它发回以指示调用端方法已经返回。

双向通信允许应用程序和底层架构将错误信息发回给客户端。设置IsOneWay=true 是阻止创建一条返回消息并发送出去的唯一方式。One-Way Services

4. 方便的日志诊断

   1: <diagnostics wmiProviderEnabled="true" 
   2:              performanceCounters="All">
   3:     <messageLogging logMalformedMessages="true" 
   4:                     logMessagesAtTransportLevel="true" />
   5: </diagnostics>
   1: <system.diagnostics>
   2:     <sources>
   3:       <source name="System.ServiceModel.MessageLogging" 
   4:               switchValue="Warning, ActivityTracing">
   5:         <listeners>
   6:           <add type="System.Diagnostics.DefaultTraceListener" 
   7:                name="Default">
   8:             <filter type="" />
   9:           </add>
  10:           <add name="ServiceModelMessageLoggingListener">
  11:             <filter type="" />
  12:           </add>
  13:         </listeners>
  14:       </source>
  15:       <source name="System.ServiceModel" 
  16:               switchValue="Warning, ActivityTracing"
  17:                     propagateActivity="true">
  18:         <listeners>
  19:           <add type="System.Diagnostics.DefaultTraceListener" 
  20:                name="Default">
  21:             <filter type="" />
  22:           </add>
  23:           <add name="ServiceModelTraceListener">
  24:             <filter type="" />
  25:           </add>
  26:         </listeners>
  27:       </source>
  28:     </sources>
  29:     <sharedListeners>
  30:       <add initializeData="app_messages.svclog"
  31:               type="System.Diagnostics.XmlWriterTraceListener, 
  32:         System, Version=2.0.0.0, Culture=neutral, 
  33:         PublicKeyToken=b77a5c561934e089"
  34:               name="ServiceModelMessageLoggingListener" 
  35:            traceOutputOptions="Timestamp">
  36:         <filter type="" />
  37:       </add>
  38:       <add initializeData="app_tracelog.svclog"
  39:               type="System.Diagnostics.XmlWriterTraceListener, 
  40:         System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  41:               name="ServiceModelTraceListener" 
  42:            traceOutputOptions="Timestamp">
  43:         <filter type="" />
  44:       </add>
  45:     </sharedListeners>
  46:     <trace autoflush="true" />
  47:   </system.diagnostics>

5. 判断服务启动

通过4提供的方法打开诊断日志,找到如下标识,就可以知道自己的服务是否开启。

ServiceHost

这主要用来判断在服务寄宿时服务是否按照我们设计的打开,以及是否打开的是正确的服务,对于排错很关键。