2 // Methods.cs: Information about a method and its mapping to a SOAP web service.
7 // (C) 2003 Ximian, Inc.
13 using System.Reflection;
14 using System.Collections;
15 using System.Xml.Serialization;
16 using System.Web.Services;
17 using System.Web.Services.Description;
19 namespace System.Web.Services.Protocols {
22 // This class represents all the information we extract from a MethodInfo
23 // in the SoapHttpClientProtocol derivative stub class
25 internal class MethodStubInfo {
26 internal LogicalMethodInfo MethodInfo;
28 // The name used bythe stub class to reference this method.
31 internal string Action;
32 internal string Binding;
34 // The name/namespace of the request
35 internal string RequestName;
36 internal string RequestNamespace;
38 // The name/namespace of the response.
39 internal string ResponseName;
40 internal string ResponseNamespace;
43 internal SoapParameterStyle ParameterStyle;
45 internal XmlSerializer RequestSerializer;
46 internal XmlSerializer ResponseSerializer;
51 MethodStubInfo (TypeStubInfo parent, LogicalMethodInfo source, object kind, XmlReflectionImporter importer)
55 if (kind is SoapDocumentMethodAttribute){
56 SoapDocumentMethodAttribute dma = (SoapDocumentMethodAttribute) kind;
58 SoapBindingUse use = dma.Use;
59 if (use == SoapBindingUse.Default)
61 if (use != SoapBindingUse.Literal)
62 throw new Exception ("Only SoapBindingUse.Literal supported");
65 Binding = dma.Binding;
66 RequestName = dma.RequestElementName;
67 RequestNamespace = dma.RequestNamespace;
68 ResponseName = dma.ResponseElementName;
69 ResponseNamespace = dma.ResponseNamespace;
70 ParameterStyle = dma.ParameterStyle;
71 if (ParameterStyle == SoapParameterStyle.Default)
72 ParameterStyle = parent.ParameterStyle;
75 SoapRpcMethodAttribute rma = (SoapRpcMethodAttribute) kind;
77 // Assuem that the TypeStub already caught any possible use of Encoded
79 Binding = rma.Binding;
80 RequestName = rma.RequestElementName;
81 RequestNamespace = rma.RequestNamespace;
82 ResponseNamespace = rma.ResponseNamespace;
83 ResponseName = rma.ResponseElementName;
87 Binding = parent.BindingName;
88 if (RequestName == "")
89 RequestName = source.Name;
92 if (source.ReturnType != typeof (void))
93 throw new Exception ("OneWay methods should not have a return value");
94 if (source.OutParameters.Length != 0)
95 throw new Exception ("OneWay methods should not have out/ref parameters");
98 object [] o = source.GetCustomAttributes (typeof (WebMethodAttribute));
100 WebMethodAttribute wma = (WebMethodAttribute) o [0];
102 Name = wma.MessageName;
108 if (ResponseName == "")
109 ResponseName = Name + "Response";
111 MakeRequestSerializer (importer);
112 MakeResponseSerializer (importer);
115 static internal MethodStubInfo Create (TypeStubInfo parent, LogicalMethodInfo lmi, XmlReflectionImporter importer)
117 object [] o = lmi.GetCustomAttributes (typeof (SoapDocumentMethodAttribute));
119 o = lmi.GetCustomAttributes (typeof (SoapRpcMethodAttribute));
122 return new MethodStubInfo (parent, lmi, o [0], importer);
124 return new MethodStubInfo (parent, lmi, o [0], importer);
127 void MakeRequestSerializer (XmlReflectionImporter importer)
129 ParameterInfo [] input = MethodInfo.InParameters;
130 XmlReflectionMember [] in_members = new XmlReflectionMember [input.Length];
132 for (int i = 0; i < input.Length; i++){
133 XmlReflectionMember m = new XmlReflectionMember ();
134 m.IsReturnValue = false;
135 m.MemberName = input [i].Name;
136 m.MemberType = input [i].ParameterType;
137 if (m.MemberType.IsByRef)
138 m.MemberType = m.MemberType.GetElementType ();
143 XmlMembersMapping [] members = new XmlMembersMapping [1];
145 Console.WriteLine ("XmLSerializer: {0} {1}", RequestName, RequestNamespace);
146 members [0] = importer.ImportMembersMapping (RequestName, RequestNamespace, in_members, true);
147 XmlSerializer [] s = null;
148 s = XmlSerializer.FromMappings (members);
149 RequestSerializer = s [0];
151 Console.WriteLine ("Got exception while creating serializer");
152 Console.WriteLine ("Method name: " + RequestName + " parameters are:");
154 for (int i = 0; i < input.Length; i++){
155 Console.WriteLine (" {0}: {1} {2}", i, in_members [i].MemberName, in_members [i].MemberType);
161 void MakeResponseSerializer (XmlReflectionImporter importer)
163 ParameterInfo [] output = MethodInfo.OutParameters;
164 bool has_return_value = !(OneWay || MethodInfo.ReturnType == typeof (void));
165 XmlReflectionMember [] out_members = new XmlReflectionMember [(has_return_value ? 1 : 0) + output.Length];
166 XmlReflectionMember m;
169 if (has_return_value){
170 m = new XmlReflectionMember ();
171 m.IsReturnValue = true;
172 m.MemberName = RequestName + "Result";
173 m.MemberType = MethodInfo.ReturnType;
178 for (int i = 0; i < output.Length; i++){
179 m = new XmlReflectionMember ();
180 m.IsReturnValue = false;
181 m.MemberName = output [i].Name;
182 m.MemberType = output [i].ParameterType;
184 if (m.MemberType.IsByRef)
185 m.MemberType = m.MemberType.GetElementType ();
186 out_members [i + idx] = m;
190 XmlMembersMapping [] members = new XmlMembersMapping [1];
191 members [0] = importer.ImportMembersMapping (ResponseName, ResponseNamespace, out_members, true);
192 XmlSerializer [] s = XmlSerializer.FromMappings (members);
193 ResponseSerializer = s [0];
195 Console.WriteLine ("Got exception while creating serializer");
196 Console.WriteLine ("Method name: " + ResponseName + " parameters are:");
198 for (int i = 0; i < out_members.Length; i++){
199 Console.WriteLine (" {0}: {1} {2}", i, out_members [i].MemberName, out_members [i].MemberType);
207 // Holds the metadata loaded from the type stub, as well as
208 // the metadata for all the methods in the type
210 internal class TypeStubInfo {
211 Hashtable name_to_method = new Hashtable ();
214 internal SoapParameterStyle ParameterStyle;
215 internal SoapServiceRoutingStyle RoutingStyle;
216 internal SoapBindingUse Use;
217 internal string WebServiceName;
218 internal string WebServiceNamespace;
219 internal string BindingLocation;
220 internal string BindingName;
221 internal string BindingNamespace;
223 void GetTypeAttributes (Type t)
227 o = t.GetCustomAttributes (typeof (WebServiceBindingAttribute), false);
229 throw new Exception ("Expected WebServiceBindingAttribute on "+ t.Name);
230 WebServiceBindingAttribute b = (WebServiceBindingAttribute) o [0];
231 BindingLocation = b.Location;
232 BindingName = b.Name;
233 BindingNamespace = b.Namespace;
235 o = t.GetCustomAttributes (typeof (WebService), false);
237 WebServiceAttribute a = (WebServiceAttribute) o [0];
239 WebServiceName = a.Name;
240 WebServiceNamespace = a.Namespace;
242 WebServiceName = t.Name;
243 WebServiceNamespace = WebServiceAttribute.DefaultNamespace;
246 o = t.GetCustomAttributes (typeof (SoapDocumentServiceAttribute), false);
248 SoapDocumentServiceAttribute a = (SoapDocumentServiceAttribute) o [0];
250 ParameterStyle = a.ParameterStyle;
251 RoutingStyle = a.RoutingStyle;
254 o = t.GetCustomAttributes (typeof (SoapRpcServiceAttribute), false);
256 SoapRpcServiceAttribute srs = (SoapRpcServiceAttribute) o [0];
258 ParameterStyle = SoapParameterStyle.Wrapped;
259 RoutingStyle = srs.RoutingStyle;
260 Use = SoapBindingUse.Literal;
262 ParameterStyle = SoapParameterStyle.Wrapped;
263 RoutingStyle = SoapServiceRoutingStyle.SoapAction;
264 Use = SoapBindingUse.Literal;
270 // Extract all method information
272 void GetTypeMethods (Type t, XmlReflectionImporter importer)
274 MethodInfo [] type_methods = t.GetMethods (BindingFlags.Instance | BindingFlags.Public);
275 LogicalMethodInfo [] methods = LogicalMethodInfo.Create (type_methods, LogicalMethodTypes.Sync);
277 foreach (LogicalMethodInfo mi in methods){
278 MethodStubInfo msi = MethodStubInfo.Create (this, mi, importer);
283 name_to_method [msi.Name] = msi;
287 internal TypeStubInfo (Type t)
289 GetTypeAttributes (t);
291 XmlReflectionImporter importer = new XmlReflectionImporter ();
292 GetTypeMethods (t, importer);
295 internal MethodStubInfo GetMethod (string name)
297 return (MethodStubInfo) name_to_method [name];
304 internal class TypeStubManager {
305 static Hashtable type_to_manager;
307 static TypeStubManager ()
309 type_to_manager = new Hashtable ();
313 // This needs to be thread safe
315 static internal TypeStubInfo GetTypeStub (Type t)
317 TypeStubInfo tm = (TypeStubInfo) type_to_manager [t];
322 lock (typeof (TypeStubInfo)){
323 tm = (TypeStubInfo) type_to_manager [t];
328 tm = new TypeStubInfo (t);
329 type_to_manager [t] = tm;