1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4 
5 namespace System.ServiceModel.Dispatcher
6 {
7     using System;
8     using System.Collections.Generic;
9     using System.Runtime;
10     using System.Runtime.Serialization;
11     using System.ServiceModel;
12     using System.Xml;
13     using System.Xml.Serialization;
14     using DiagnosticUtility = System.ServiceModel.DiagnosticUtility;
15 
16     class UnwrappedTypesXmlSerializerManager
17     {
18         Dictionary<Type, XmlTypeMapping> allTypes;
19         XmlReflectionImporter importer;
20         Dictionary<Object, IList<Type>> operationTypes;
21         bool serializersCreated;
22         Dictionary<Type, XmlSerializer> serializersMap;
23         Object thisLock;
24 
UnwrappedTypesXmlSerializerManager()25         public UnwrappedTypesXmlSerializerManager()
26         {
27             this.allTypes = new Dictionary<Type, XmlTypeMapping>();
28             this.serializersMap = new Dictionary<Type, XmlSerializer>();
29             this.operationTypes = new Dictionary<Object, IList<Type>>();
30             importer = new XmlReflectionImporter();
31             this.thisLock = new Object();
32         }
33 
GetOperationSerializers(Object key)34         public TypeSerializerPair[] GetOperationSerializers(Object key)
35         {
36             if (key == null)
37             {
38                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("key");
39             }
40             lock (thisLock)
41             {
42                 if (!this.serializersCreated)
43                 {
44                     BuildSerializers();
45                     this.serializersCreated = true;
46                 }
47                 List<TypeSerializerPair> serializers = new List<TypeSerializerPair>();
48                 IList<Type> operationTypes = this.operationTypes[key];
49                 for (int i = 0; i < operationTypes.Count; ++i)
50                 {
51                     TypeSerializerPair pair = new TypeSerializerPair();
52                     pair.Type = operationTypes[i];
53                     pair.Serializer = new XmlSerializerXmlObjectSerializer(serializersMap[operationTypes[i]]);
54                     serializers.Add(pair);
55                 }
56                 return serializers.ToArray();
57             }
58         }
59 
RegisterType(Object key, IList<Type> types)60         public void RegisterType(Object key, IList<Type> types)
61         {
62             if (key == null)
63             {
64                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("key");
65             }
66             if (types == null)
67             {
68                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("types");
69             }
70             lock (thisLock)
71             {
72                 if (this.serializersCreated)
73                 {
74                     Fx.Assert("An xml serializer type was added after the serializers were created");
75                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.XmlSerializersCreatedBeforeRegistration)));
76                 }
77                 for (int i = 0; i < types.Count; ++i)
78                 {
79                     if (!allTypes.ContainsKey(types[i]))
80                     {
81                         allTypes.Add(types[i], importer.ImportTypeMapping(types[i]));
82                     }
83                 }
84                 operationTypes.Add(key, types);
85             }
86         }
87 
BuildSerializers()88         void BuildSerializers()
89         {
90             List<Type> types = new List<Type>();
91             List<XmlMapping> mappings = new List<XmlMapping>();
92             foreach (Type type in allTypes.Keys)
93             {
94                 XmlTypeMapping mapping = allTypes[type];
95                 types.Add(type);
96                 mappings.Add(mapping);
97             }
98             XmlSerializer[] serializers = XmlSerializer.FromMappings(mappings.ToArray());
99             for (int i = 0; i < types.Count; ++i)
100             {
101                 serializersMap.Add(types[i], serializers[i]);
102             }
103         }
104 
105         public struct TypeSerializerPair
106         {
107             public XmlObjectSerializer Serializer;
108             public Type Type;
109         }
110 
111         class XmlSerializerXmlObjectSerializer : XmlObjectSerializer
112         {
113             XmlSerializer serializer;
114 
XmlSerializerXmlObjectSerializer(XmlSerializer serializer)115             public XmlSerializerXmlObjectSerializer(XmlSerializer serializer)
116             {
117                 if (serializer == null)
118                 {
119                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serializer");
120                 }
121                 this.serializer = serializer;
122             }
123 
IsStartObject(XmlDictionaryReader reader)124             public override bool IsStartObject(XmlDictionaryReader reader)
125             {
126                 return this.serializer.CanDeserialize(reader);
127             }
128 
ReadObject(XmlDictionaryReader reader, bool verifyObjectName)129             public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
130             {
131                 return this.serializer.Deserialize(reader);
132             }
133 
WriteEndObject(XmlDictionaryWriter writer)134             public override void WriteEndObject(XmlDictionaryWriter writer)
135             {
136                 Fx.Assert("This method should never get hit");
137                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
138             }
139 
WriteObject(XmlDictionaryWriter writer, object graph)140             public override void WriteObject(XmlDictionaryWriter writer, object graph)
141             {
142                 this.serializer.Serialize(writer, graph);
143             }
144 
WriteObjectContent(XmlDictionaryWriter writer, object graph)145             public override void WriteObjectContent(XmlDictionaryWriter writer, object graph)
146             {
147                 Fx.Assert("This method should never get hit");
148                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
149             }
150 
WriteStartObject(XmlDictionaryWriter writer, object graph)151             public override void WriteStartObject(XmlDictionaryWriter writer, object graph)
152             {
153                 Fx.Assert("This method should never get hit");
154                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
155             }
156         }
157     }
158 }
159 
160