1 //----------------------------------------------------------------------------- 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //----------------------------------------------------------------------------- 4 5 namespace System.ServiceModel.Description 6 { 7 using System; 8 using System.ServiceModel.Channels; 9 using System.Configuration; 10 using System.Collections.Generic; 11 using System.ServiceModel; 12 using System.ServiceModel.Configuration; 13 using System.ServiceModel.Diagnostics; 14 15 internal class ConfigWriter 16 { 17 readonly Dictionary<Binding, BindingDictionaryValue> bindingTable; 18 readonly BindingsSection bindingsSection; 19 readonly ChannelEndpointElementCollection channels; 20 readonly Configuration config; 21 ConfigWriter(Configuration configuration)22 internal ConfigWriter(Configuration configuration) 23 { 24 this.bindingTable = new Dictionary<Binding, BindingDictionaryValue>(); 25 26 this.bindingsSection = BindingsSection.GetSection(configuration); 27 28 ServiceModelSectionGroup serviceModelSectionGroup = ServiceModelSectionGroup.GetSectionGroup(configuration); 29 this.channels = serviceModelSectionGroup.Client.Endpoints; 30 this.config = configuration; 31 } 32 WriteChannelDescription(ServiceEndpoint endpoint, string typeName)33 internal ChannelEndpointElement WriteChannelDescription(ServiceEndpoint endpoint, string typeName) 34 { 35 ChannelEndpointElement channelElement = null; 36 37 // Create Binding 38 BindingDictionaryValue bindingDV = CreateBindingConfig(endpoint.Binding); 39 40 41 channelElement = new ChannelEndpointElement(endpoint.Address, typeName); 42 43 // Microsoft: review: Use decoded form to preserve the user-given friendly name, however, beacuse our Encoding algorithm 44 // does not touch ASCII names, a name that looks like encoded name will not roundtrip(Example: "_x002C_" will turned into ",") 45 channelElement.Name = NamingHelper.GetUniqueName(NamingHelper.CodeName(endpoint.Name), this.CheckIfChannelNameInUse, null); 46 47 channelElement.BindingConfiguration = bindingDV.BindingName; 48 channelElement.Binding = bindingDV.BindingSectionName; 49 channels.Add(channelElement); 50 51 return channelElement; 52 } 53 WriteBinding(Binding binding, out string bindingSectionName, out string configurationName)54 internal void WriteBinding(Binding binding, out string bindingSectionName, out string configurationName) 55 { 56 BindingDictionaryValue result = CreateBindingConfig(binding); 57 58 configurationName = result.BindingName; 59 bindingSectionName = result.BindingSectionName; 60 } 61 CreateBindingConfig(Binding binding)62 BindingDictionaryValue CreateBindingConfig(Binding binding) 63 { 64 BindingDictionaryValue bindingDV; 65 if (!bindingTable.TryGetValue(binding, out bindingDV)) 66 { 67 // Microsoft: review: Use decoded form to preserve the user-given friendly name, however, beacuse our Encoding algorithm 68 // does not touch ASCII names, a name that looks like encoded name will not roundtrip(Example: "_x002C_" will turned into ",") 69 string bindingName = NamingHelper.GetUniqueName(NamingHelper.CodeName(binding.Name), this.CheckIfBindingNameInUse, null); 70 string bindingSectionName; 71 72 if (!BindingsSection.TryAdd(bindingName, binding, config, out bindingSectionName)) 73 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.ConfigBindingCannotBeConfigured), "endpoint.Binding")); 74 75 bindingDV = new BindingDictionaryValue(bindingName, bindingSectionName); 76 bindingTable.Add(binding, bindingDV); 77 } 78 return bindingDV; 79 } 80 CheckIfBindingNameInUse(string name, object nameCollection)81 bool CheckIfBindingNameInUse(string name, object nameCollection) 82 { 83 foreach (BindingCollectionElement bindingCollectionElement in this.bindingsSection.BindingCollections) 84 if (bindingCollectionElement.ContainsKey(name)) 85 return true; 86 87 return false; 88 } 89 CheckIfChannelNameInUse(string name, object namingCollection)90 bool CheckIfChannelNameInUse(string name, object namingCollection) 91 { 92 foreach (ChannelEndpointElement element in this.channels) 93 if (element.Name == name) 94 return true; 95 96 return false; 97 } 98 99 sealed class BindingDictionaryValue 100 { 101 public readonly string BindingName; 102 public readonly string BindingSectionName; 103 BindingDictionaryValue(string bindingName, string bindingSectionName)104 public BindingDictionaryValue(string bindingName, string bindingSectionName) 105 { 106 this.BindingName = bindingName; 107 this.BindingSectionName = bindingSectionName; 108 } 109 } 110 111 } 112 } 113