做了许许多多的WCF的开发,当自己的项目中引用越来越多的服务之后发现程序的配置文件越来越庞大,维护起这个配置文件来也就比较困难了。其实我们完全可以把这些WCF的配置分离出来到单独的文件中。这样使得服务的配置和程序的配置都很容易维护。
实现这个功能其实很简单,只需要重载一下ChannelFactory<T>里的一些方法。
这个类就是负责加载配置信息的类。下面给出我的代码:

Code
希望会对其他人有些帮助
1
/**//// <summary>
2
/// 自定义的客户端信道(允许从自定义的配置文件中加载)
3
/// </summary>
4
/// <typeparam name="T"></typeparam>
5
public class CustomClientChannel<T> : ChannelFactory<T>
6
{
7
string configurationPath;
8
string endpointConfigurationName;
9
10
/**//// <summary>
11
/// 构造函数
12
/// </summary>
13
/// <param name="configurationPath"></param>
14
public CustomClientChannel(string configurationPath)
15
: base(typeof(T))
16
{
17
this.configurationPath = configurationPath;
18
base.InitializeEndpoint((string)null, null);
19
}
20
21
/**//// <summary>
22
/// 构造函数
23
/// </summary>
24
/// <param name="binding"></param>
25
/// <param name="configurationPath"></param>
26
public CustomClientChannel(Binding binding, string configurationPath)
27
: this(binding, (EndpointAddress)null, configurationPath)
28
{
29
}
30
31
/**//// <summary>
32
/// 构造函数
33
/// </summary>
34
/// <param name="serviceEndpoint"></param>
35
/// <param name="configurationPath"></param>
36
public CustomClientChannel(ServiceEndpoint serviceEndpoint, string configurationPath)
37
: base(typeof(T))
38
{
39
this.configurationPath = configurationPath;
40
base.InitializeEndpoint(serviceEndpoint);
41
}
42
43
/**//// <summary>
44
/// 构造函数
45
/// </summary>
46
/// <param name="endpointConfigurationName"></param>
47
/// <param name="configurationPath"></param>
48
public CustomClientChannel(string endpointConfigurationName, string configurationPath)
49
: this(endpointConfigurationName, null, configurationPath)
50
{
51
}
52
53
/**//// <summary>
54
/// 构造函数
55
/// </summary>
56
/// <param name="binding"></param>
57
/// <param name="endpointAddress"></param>
58
/// <param name="configurationPath"></param>
59
public CustomClientChannel(Binding binding, EndpointAddress endpointAddress, string configurationPath)
60
: base(typeof(T))
61
{
62
this.configurationPath = configurationPath;
63
base.InitializeEndpoint(binding, endpointAddress);
64
}
65
66
/**//// <summary>
67
/// 构造函数
68
/// </summary>
69
/// <param name="binding"></param>
70
/// <param name="remoteAddress"></param>
71
/// <param name="configurationPath"></param>
72
public CustomClientChannel(Binding binding, string remoteAddress, string configurationPath)
73
: this(binding, new EndpointAddress(remoteAddress), configurationPath)
74
{
75
}
76
77
/**//// <summary>
78
/// 构造函数
79
/// </summary>
80
/// <param name="endpointConfigurationName"></param>
81
/// <param name="endpointAddress"></param>
82
/// <param name="configurationPath"></param>
83
public CustomClientChannel(string endpointConfigurationName, EndpointAddress endpointAddress, string configurationPath)
84
: base(typeof(T))
85
{
86
this.configurationPath = configurationPath;
87
this.endpointConfigurationName = endpointConfigurationName;
88
base.InitializeEndpoint(endpointConfigurationName, endpointAddress);
89
}
90
91
/**//// <summary>
92
/// 从自定义配置文件中加载终结点描述
93
/// </summary>
94
/// <returns></returns>
95
protected override ServiceEndpoint CreateDescription()
96
{
97
ServiceEndpoint serviceEndpoint = base.CreateDescription();
98
99
if (endpointConfigurationName != null)
100
serviceEndpoint.Name = endpointConfigurationName;
101
102
ExeConfigurationFileMap map = new ExeConfigurationFileMap();
103
map.ExeConfigFilename = this.configurationPath;
104
105
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
106
ServiceModelSectionGroup group = ServiceModelSectionGroup.GetSectionGroup(config);
107
108
ChannelEndpointElement selectedEndpoint = null;
109
110
foreach (ChannelEndpointElement endpoint in group.Client.Endpoints)
111
{
112
if (endpoint.Contract == serviceEndpoint.Contract.ConfigurationName &&
113
(this.endpointConfigurationName == null || this.endpointConfigurationName == endpoint.Name))
114
{
115
selectedEndpoint = endpoint;
116
break;
117
}
118
}
119
120
if (selectedEndpoint != null)
121
{
122
if (serviceEndpoint.Binding == null)
123
{
124
serviceEndpoint.Binding = CreateBinding(selectedEndpoint.Binding, group);
125
}
126
127
if (serviceEndpoint.Address == null)
128
{
129
serviceEndpoint.Address = new EndpointAddress(selectedEndpoint.Address, GetIdentity(selectedEndpoint.Identity), selectedEndpoint.Headers.Headers);
130
}
131
132
if (serviceEndpoint.Behaviors.Count == 0 && selectedEndpoint.BehaviorConfiguration != null)
133
{
134
AddBehaviors(selectedEndpoint.BehaviorConfiguration, serviceEndpoint, group);
135
}
136
137
serviceEndpoint.Name = selectedEndpoint.Contract;
138
}
139
140
return serviceEndpoint;
141
142
}
143
144
/**//// <summary>
145
/// 为所选择的终结点配置绑定
146
/// </summary>
147
/// <param name="bindingName"></param>
148
/// <param name="group"></param>
149
/// <returns></returns>
150
private Binding CreateBinding(string bindingName, ServiceModelSectionGroup group)
151
{
152
BindingCollectionElement bindingElementCollection = group.Bindings[bindingName];
153
if (bindingElementCollection.ConfiguredBindings.Count > 0)
154
{
155
IBindingConfigurationElement be = bindingElementCollection.ConfiguredBindings[0];
156
157
Binding binding = GetBinding(be);
158
if (be != null)
159
{
160
be.ApplyConfiguration(binding);
161
}
162
163
return binding;
164
}
165
166
return null;
167
}
168
169
/**//// <summary>
170
/// 一些创建匹配绑定的方法
171
/// </summary>
172
/// <param name="configurationElement"></param>
173
/// <returns></returns>
174
private Binding GetBinding(IBindingConfigurationElement configurationElement)
175
{
176
if (configurationElement is CustomBindingElement)
177
return new CustomBinding();
178
else if (configurationElement is BasicHttpBindingElement)
179
return new BasicHttpBinding();
180
else if (configurationElement is NetMsmqBindingElement)
181
return new NetMsmqBinding();
182
else if (configurationElement is NetNamedPipeBindingElement)
183
return new NetNamedPipeBinding();
184
else if (configurationElement is NetPeerTcpBindingElement)
185
return new NetPeerTcpBinding();
186
else if (configurationElement is NetTcpBindingElement)
187
return new NetTcpBinding();
188
else if (configurationElement is WSDualHttpBindingElement)
189
return new WSDualHttpBinding();
190
else if (configurationElement is WSHttpBindingElement)
191
return new WSHttpBinding();
192
else if (configurationElement is WSFederationHttpBindingElement)
193
return new WSFederationHttpBinding();
194
195
return null;
196
}
197
198
/**//// <summary>
199
/// 添加configured behavior 到所选择的终结点
200
/// </summary>
201
/// <param name="behaviorConfiguration"></param>
202
/// <param name="serviceEndpoint"></param>
203
/// <param name="group"></param>
204
private void AddBehaviors(string behaviorConfiguration, ServiceEndpoint serviceEndpoint, ServiceModelSectionGroup group)
205
{
206
//如果没有配置客户端行为则不执行
207
if (String.IsNullOrEmpty(behaviorConfiguration))
208
{
209
return;
210
}
211
212
EndpointBehaviorElement behaviorElement = group.Behaviors.EndpointBehaviors[behaviorConfiguration];
213
for (int i = 0; i < behaviorElement.Count; i++)
214
{
215
BehaviorExtensionElement behaviorExtension = behaviorElement[i];
216
object extension = behaviorExtension.GetType().InvokeMember("CreateBehavior",
217
BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
218
null, behaviorExtension, null);
219
if (extension != null)
220
{
221
serviceEndpoint.Behaviors.Add((IEndpointBehavior)extension);
222
}
223
}
224
}
225
226
/**//// <summary>
227
/// 从配置文件重获取终结点的identity
228
/// </summary>
229
/// <param name="element"></param>
230
/// <returns></returns>
231
private EndpointIdentity GetIdentity(IdentityElement element)
232
{
233
EndpointIdentity identity = null;
234
PropertyInformationCollection properties = element.ElementInformation.Properties;
235
if (properties["userPrincipalName"].ValueOrigin != PropertyValueOrigin.Default)
236
{
237
return EndpointIdentity.CreateUpnIdentity(element.UserPrincipalName.Value);
238
}
239
if (properties["servicePrincipalName"].ValueOrigin != PropertyValueOrigin.Default)
240
{
241
return EndpointIdentity.CreateSpnIdentity(element.ServicePrincipalName.Value);
242
}
243
if (properties["dns"].ValueOrigin != PropertyValueOrigin.Default)
244
{
245
return EndpointIdentity.CreateDnsIdentity(element.Dns.Value);
246
}
247
if (properties["rsa"].ValueOrigin != PropertyValueOrigin.Default)
248
{
249
return EndpointIdentity.CreateRsaIdentity(element.Rsa.Value);
250
}
251
if (properties["certificate"].ValueOrigin != PropertyValueOrigin.Default)
252
{
253
X509Certificate2Collection supportingCertificates = new X509Certificate2Collection();
254
supportingCertificates.Import(Convert.FromBase64String(element.Certificate.EncodedValue));
255
if (supportingCertificates.Count == 0)
256
{
257
throw new InvalidOperationException("UnableToLoadCertificateIdentity");
258
}
259
X509Certificate2 primaryCertificate = supportingCertificates[0];
260
supportingCertificates.RemoveAt(0);
261
return EndpointIdentity.CreateX509CertificateIdentity(primaryCertificate, supportingCertificates);
262
}
263
264
return identity;
265
}
266
267
268
protected override void ApplyConfiguration(string configurationName)
269
{
270
base.ApplyConfiguration(configurationName);
271
}
272
273
}