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