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提供的方法打开诊断日志,找到如下标识,就可以知道自己的服务是否开启。
这主要用来判断在服务寄宿时服务是否按照我们设计的打开,以及是否打开的是正确的服务,对于排错很关键。