1: using System;
2: using System.ServiceModel.Configuration;
3: using System.Reflection;
4: using System.Security.Cryptography.X509Certificates;
5: using System.ServiceModel;
6: using System.ServiceModel.Description;
7: using System.ServiceModel.Channels;
8: using System.Configuration;
9:
10: namespace MAS.Interface.Client
11: {
12: public class ManualChannelFactory<T> : ChannelFactory<T>
13: {
14: string configurationPath;
15: Uri overrideEndPoint;
16:
17: /// <summary>
18: /// custom client channel constructor which
19: /// specifies an external configuration file
20: /// </summary>
21: /// <param name="configurationPath"></param>
22: public ManualChannelFactory(string configurationPath)
23: : base(typeof(T))
24: {
25: this.configurationPath = configurationPath;
26: base.InitializeEndpoint((string)null, null);
27: }
28:
29: /// <summary>
30: /// Initializes a new instance of the <see cref="ManualChannelFactory<T>"/> class.
31: /// </summary>
32: /// <param name="configurationPath">The configuration path.</param>
33: /// <param name="overrideEndPoint">The override end point.</param>
34: public ManualChannelFactory(string configurationPath, Uri overrideEndPoint)
35: : base(typeof(T))
36: {
37: this.configurationPath = configurationPath;
38: this.overrideEndPoint = overrideEndPoint;
39: base.InitializeEndpoint((string)null, null);
40: }
41:
42: /// <summary>
43: /// overrides the CreateDescription() method of the channel factory
44: /// to apply a new configuration file
45: /// </summary>
46: /// <returns></returns>
47: protected override ServiceEndpoint CreateDescription()
48: {
49: ServiceEndpoint serviceEndpoint = base.CreateDescription();
50:
51: ExeConfigurationFileMap executionFileMap = new ExeConfigurationFileMap();
52: executionFileMap.ExeConfigFilename = configurationPath;
53:
54: System.Configuration.Configuration config = ConfigurationManager.OpenMappedExeConfiguration(executionFileMap, ConfigurationUserLevel.None);
55: ServiceModelSectionGroup serviceModeGroup = ServiceModelSectionGroup.GetSectionGroup(config);
56:
57: ChannelEndpointElement selectedEndpoint = null;
58:
59: foreach (ChannelEndpointElement endpoint in serviceModeGroup.Client.Endpoints)
60: {
61: if (endpoint.Contract == serviceEndpoint.Contract.ConfigurationName)
62: {
63: selectedEndpoint = endpoint;
64: break;
65: }
66: }
67:
68: if (selectedEndpoint != null)
69: {
70: if (serviceEndpoint.Binding == null)
71: {
72: serviceEndpoint.Binding = CreateBinding(selectedEndpoint.Binding, serviceModeGroup);
73: }
74:
75: if (serviceEndpoint.Address == null)
76: {
77: if (overrideEndPoint == null)
78: {
79: serviceEndpoint.Address = new EndpointAddress(selectedEndpoint.Address, GetIdentity(selectedEndpoint.Identity), selectedEndpoint.Headers.Headers);
80: }
81: else
82: {
83: serviceEndpoint.Address = new EndpointAddress(overrideEndPoint, GetIdentity(selectedEndpoint.Identity), selectedEndpoint.Headers.Headers);
84: }
85: }
86:
87: if (serviceEndpoint.Behaviors.Count == 0 && !String.IsNullOrEmpty(selectedEndpoint.BehaviorConfiguration))
88: {
89: AddBehaviors(selectedEndpoint.BehaviorConfiguration, serviceEndpoint, serviceModeGroup);
90: }
91:
92: serviceEndpoint.Name = selectedEndpoint.Contract;
93: }
94:
95: return serviceEndpoint;
96: }
97:
98: /// <summary>
99: /// Configures the binding for the selected endpoint
100: /// </summary>
101: /// <param name="bindingName"></param>
102: /// <param name="group"></param>
103: /// <returns></returns>
104: private Binding CreateBinding(string bindingName, ServiceModelSectionGroup group)
105: {
106: BindingCollectionElement bindingElementCollection = group.Bindings[bindingName];
107: if (bindingElementCollection.ConfiguredBindings.Count > 0)
108: {
109: IBindingConfigurationElement be = bindingElementCollection.ConfiguredBindings[0];
110:
111: Binding binding = GetBinding(be);
112: if (be != null)
113: {
114: be.ApplyConfiguration(binding);
115: }
116:
117: return binding;
118: }
119:
120: return null;
121: }
122:
123: /// <summary>
124: /// Adds the configured behavior to the selected endpoint
125: /// </summary>
126: /// <param name="behaviorConfiguration"></param>
127: /// <param name="serviceEndpoint"></param>
128: /// <param name="group"></param>
129: private void AddBehaviors(string behaviorConfiguration, ServiceEndpoint serviceEndpoint, ServiceModelSectionGroup group)
130: {
131: EndpointBehaviorElement behaviorElement = group.Behaviors.EndpointBehaviors[behaviorConfiguration];
132: for (int i = 0; i < behaviorElement.Count; i++)
133: {
134: BehaviorExtensionElement behaviorExtension = behaviorElement[i];
135: object extension = behaviorExtension.GetType().InvokeMember("CreateBehavior",
136: BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
137: null, behaviorExtension, null);
138: if (extension != null)
139: {
140: serviceEndpoint.Behaviors.Add((IEndpointBehavior)extension);
141: }
142: }
143: }
144:
145: /// <summary>
146: /// Gets the endpoint identity from the configuration file
147: /// </summary>
148: /// <param name="element"></param>
149: /// <returns></returns>
150: private EndpointIdentity GetIdentity(IdentityElement element)
151: {
152: EndpointIdentity identity = null;
153: PropertyInformationCollection properties = element.ElementInformation.Properties;
154: if (properties["userPrincipalName"].ValueOrigin != PropertyValueOrigin.Default)
155: {
156: return EndpointIdentity.CreateUpnIdentity(element.UserPrincipalName.Value);
157: }
158: if (properties["servicePrincipalName"].ValueOrigin != PropertyValueOrigin.Default)
159: {
160: return EndpointIdentity.CreateSpnIdentity(element.ServicePrincipalName.Value);
161: }
162: if (properties["dns"].ValueOrigin != PropertyValueOrigin.Default)
163: {
164: return EndpointIdentity.CreateDnsIdentity(element.Dns.Value);
165: }
166: if (properties["rsa"].ValueOrigin != PropertyValueOrigin.Default)
167: {
168: return EndpointIdentity.CreateRsaIdentity(element.Rsa.Value);
169: }
170: if (properties["certificate"].ValueOrigin != PropertyValueOrigin.Default)
171: {
172: X509Certificate2Collection supportingCertificates = new X509Certificate2Collection();
173: supportingCertificates.Import(Convert.FromBase64String(element.Certificate.EncodedValue));
174: if (supportingCertificates.Count == 0)
175: {
176: throw new InvalidOperationException("UnableToLoadCertificateIdentity");
177: }
178: X509Certificate2 primaryCertificate = supportingCertificates[0];
179: supportingCertificates.RemoveAt(0);
180: return EndpointIdentity.CreateX509CertificateIdentity(primaryCertificate, supportingCertificates);
181: }
182:
183: return identity;
184: }
185:
186: /// <summary>
187: /// Helper method to create the right binding depending on the configuration element
188: /// </summary>
189: /// <param name="configurationElement"></param>
190: /// <returns></returns>
191: private Binding GetBinding(IBindingConfigurationElement configurationElement)
192: {
193: if (configurationElement is CustomBindingElement)
194: return new CustomBinding();
195: else if (configurationElement is BasicHttpBindingElement)
196: return new BasicHttpBinding();
197: else if (configurationElement is NetMsmqBindingElement)
198: return new NetMsmqBinding();
199: else if (configurationElement is NetNamedPipeBindingElement)
200: return new NetNamedPipeBinding();
201: else if (configurationElement is NetPeerTcpBindingElement)
202: return new NetPeerTcpBinding();
203: else if (configurationElement is NetTcpBindingElement)
204: return new NetTcpBinding();
205: else if (configurationElement is WSDualHttpBindingElement)
206: return new WSDualHttpBinding();
207: else if (configurationElement is WSHttpBindingElement)
208: return new WSHttpBinding();
209: else if (configurationElement is WSFederationHttpBindingElement)
210: return new WSFederationHttpBinding();
211:
212: return null;
213: }
214: }
215: }