2 // ContractDescription.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2005 Novell, Inc. http://www.novell.com
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.Collections.ObjectModel;
32 using System.Diagnostics;
34 using System.Net.Security;
35 using System.Reflection;
36 using System.Runtime.Serialization;
37 using System.ServiceModel;
38 using System.ServiceModel.Channels;
39 using System.ServiceModel.Dispatcher;
41 namespace System.ServiceModel.Description
44 internal static class Extensions
46 public static T GetCustomAttribute<T> (this MemberInfo mi, bool inherit) where T : Attribute
48 foreach (T att in mi.GetCustomAttributes (typeof (T), inherit))
53 public static T GetCustomAttribute<T> (this ParameterInfo pi, bool inherit) where T : Attribute
55 foreach (T att in pi.GetCustomAttributes (typeof (T), inherit))
62 [DebuggerDisplay ("Name={name}, Namespace={ns}, ContractType={contractType}")]
63 public class ContractDescription
65 public static ContractDescription GetContract (
68 if (contractType == null)
69 throw new ArgumentNullException ("contractType");
70 return ContractDescriptionGenerator.GetContract (contractType);
73 public static ContractDescription GetContract (
74 Type contractType, object serviceImplementation)
76 if (contractType == null)
77 throw new ArgumentNullException ("contractType");
78 if (serviceImplementation == null)
79 throw new ArgumentNullException ("serviceImplementation");
80 return ContractDescriptionGenerator.GetContract (contractType, serviceImplementation);
83 public static ContractDescription GetContract (
84 Type contractType, Type serviceType)
86 if (contractType == null)
87 throw new ArgumentNullException ("contractType");
88 if (serviceType == null)
89 throw new ArgumentNullException ("serviceType");
90 return ContractDescriptionGenerator.GetContract (contractType, serviceType);
93 OperationDescriptionCollection operations;
94 KeyedByTypeCollection<IContractBehavior> behaviors;
95 Type callback_contract_type, contract_type;
96 string name, ns, config_name;
97 ProtectionLevel protection_level;
98 bool has_protection_level;
101 public ContractDescription (string name)
106 public ContractDescription (string name, string ns)
109 throw new ArgumentNullException ("name");
110 if (name.Length == 0)
111 throw new ArgumentOutOfRangeException ("ContractDescription's Name must be a non-empty string.");
113 ns = "http://tempuri.org/";
117 behaviors = new KeyedByTypeCollection<IContractBehavior> ();
118 operations = new OperationDescriptionCollection ();
121 public KeyedByTypeCollection<IContractBehavior> Behaviors {
122 get { return behaviors; }
125 public Type CallbackContractType {
126 get { return callback_contract_type; }
127 set { callback_contract_type = value; }
130 public string ConfigurationName {
131 get { return config_name; }
132 set { config_name = value; }
135 public Type ContractType {
136 get { return contract_type; }
137 set { contract_type = value; }
140 public bool HasProtectionLevel {
141 get { return has_protection_level; }
144 public ProtectionLevel ProtectionLevel {
145 get { return protection_level; }
147 protection_level = value;
148 has_protection_level = true;
154 set { name = value; }
157 public string Namespace {
162 public OperationDescriptionCollection Operations {
163 get { return operations; }
166 public SessionMode SessionMode {
167 get { return session; }
168 set { session = value; }
171 public Collection<ContractDescription> GetInheritedContracts ()
173 var ret = new Collection<ContractDescription> ();
174 foreach (var it in ContractType.GetInterfaces ()) {
175 var icd = ContractDescriptionGenerator.GetContractInternal (it, null, null);
182 internal ClientRuntime CreateClientRuntime (object callbackDispatchRuntime)
184 ClientRuntime proxy = new ClientRuntime (Name, Namespace, callbackDispatchRuntime) {ContractClientType = ContractType, CallbackClientType = CallbackContractType};
185 FillClientOperations (proxy, false);
189 internal void FillClientOperations (ClientRuntime proxy, bool isCallback)
191 foreach (OperationDescription od in Operations) {
192 if (!(isCallback && od.InCallbackContract || !isCallback && od.InOrdinalContract))
193 continue; // not in the contract in use.
195 if (!proxy.Operations.Contains (od.Name))
196 PopulateClientOperation (proxy, od, isCallback);
197 foreach (IOperationBehavior ob in od.Behaviors)
198 ob.ApplyClientBehavior (od, proxy.Operations [od.Name]);
202 void PopulateClientOperation (ClientRuntime proxy, OperationDescription od, bool isCallback)
204 string reqA = null, resA = null;
205 foreach (MessageDescription m in od.Messages) {
206 bool isReq = m.Direction == MessageDirection.Input ^ isCallback;
214 new ClientOperation (proxy, od.Name, reqA) :
215 new ClientOperation (proxy, od.Name, reqA, resA);
216 foreach (MessageDescription md in od.Messages) {
217 bool isReq = md.Direction == MessageDirection.Input ^ isCallback;
219 md.Body.Parts.Count == 1 &&
220 md.Body.Parts [0].Type == typeof (Message))
221 o.SerializeRequest = false;
223 md.Body.ReturnValue != null &&
224 md.Body.ReturnValue.Type == typeof (Message))
225 o.DeserializeReply = false;
227 foreach (var fd in od.Faults)
228 o.FaultContractInfos.Add (new FaultContractInfo (fd.Action, fd.DetailType));
230 // FIXME: at initialization time it does not seem to
231 // fill default formatter. It should be filled after
232 // applying all behaviors. (Tthat causes regression, so
233 // I don't care little compatibility difference so far)
235 // FIXME: pass correct isRpc, isEncoded
236 o.Formatter = new OperationFormatter (od, false, false);
238 proxy.Operations.Add (o);