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
43 internal static class Extensions
45 public static T GetCustomAttribute
<T
> (this MemberInfo mi
, bool inherit
) where T
: Attribute
47 foreach (T att
in mi
.GetCustomAttributes (typeof (T
), inherit
))
52 public static T GetCustomAttribute
<T
> (this ParameterInfo pi
, bool inherit
) where T
: Attribute
54 foreach (T att
in pi
.GetCustomAttributes (typeof (T
), inherit
))
60 [DebuggerDisplay ("Name={name}, Namespace={ns}, ContractType={contractType}")]
61 public class ContractDescription
63 public static ContractDescription
GetContract (
66 if (contractType
== null)
67 throw new ArgumentNullException ("contractType");
68 return ContractDescriptionGenerator
.GetContract (contractType
);
71 public static ContractDescription
GetContract (
72 Type contractType
, object serviceImplementation
)
74 if (contractType
== null)
75 throw new ArgumentNullException ("contractType");
76 if (serviceImplementation
== null)
77 throw new ArgumentNullException ("serviceImplementation");
78 return ContractDescriptionGenerator
.GetContract (contractType
, serviceImplementation
);
81 public static ContractDescription
GetContract (
82 Type contractType
, Type serviceType
)
84 if (contractType
== null)
85 throw new ArgumentNullException ("contractType");
86 if (serviceType
== null)
87 throw new ArgumentNullException ("serviceType");
88 return ContractDescriptionGenerator
.GetContract (contractType
, serviceType
);
91 OperationDescriptionCollection operations
;
92 KeyedByTypeCollection
<IContractBehavior
> behaviors
;
93 Type callback_contract_type
, contract_type
;
94 string name
, ns
, config_name
;
95 ProtectionLevel protection_level
;
96 bool has_protection_level
;
99 public ContractDescription (string name
)
104 public ContractDescription (string name
, string ns
)
107 throw new ArgumentNullException ("name");
108 if (name
.Length
== 0)
109 throw new ArgumentOutOfRangeException ("ContractDescription's Name must be a non-empty string.");
111 ns
= "http://tempuri.org/";
115 behaviors
= new KeyedByTypeCollection
<IContractBehavior
> ();
116 operations
= new OperationDescriptionCollection ();
119 public KeyedByTypeCollection
<IContractBehavior
> Behaviors
{
120 get { return behaviors; }
123 public Type CallbackContractType
{
124 get { return callback_contract_type; }
125 set { callback_contract_type = value; }
128 public string ConfigurationName
{
129 get { return config_name; }
130 set { config_name = value; }
133 public Type ContractType
{
134 get { return contract_type; }
135 set { contract_type = value; }
138 public bool HasProtectionLevel
{
139 get { return has_protection_level; }
142 public ProtectionLevel ProtectionLevel
{
143 get { return protection_level; }
145 protection_level
= value;
146 has_protection_level
= true;
152 set { name = value; }
155 public string Namespace
{
160 public OperationDescriptionCollection Operations
{
161 get { return operations; }
164 public SessionMode SessionMode
{
165 get { return session; }
166 set { session = value; }
169 public Collection
<ContractDescription
> GetInheritedContracts ()
171 var ret
= new Collection
<ContractDescription
> ();
172 foreach (var it
in ContractType
.GetInterfaces ()) {
173 var icd
= ContractDescriptionGenerator
.GetContractInternal (it
, null, null);
180 internal ClientRuntime
CreateClientRuntime (object callbackDispatchRuntime
)
182 ClientRuntime proxy
= new ClientRuntime (Name
, Namespace
, callbackDispatchRuntime
) {ContractClientType = ContractType, CallbackClientType = CallbackContractType}
;
183 FillClientOperations (proxy
, false);
187 internal void FillClientOperations (ClientRuntime proxy
, bool isCallback
)
189 foreach (OperationDescription od
in Operations
) {
190 if (!(isCallback
&& od
.InCallbackContract
|| !isCallback
&& od
.InOrdinalContract
))
191 continue; // not in the contract in use.
193 if (!proxy
.Operations
.Contains (od
.Name
))
194 PopulateClientOperation (proxy
, od
, isCallback
);
195 foreach (IOperationBehavior ob
in od
.Behaviors
)
196 ob
.ApplyClientBehavior (od
, proxy
.Operations
[od
.Name
]);
200 void PopulateClientOperation (ClientRuntime proxy
, OperationDescription od
, bool isCallback
)
202 string reqA
= null, resA
= null;
203 foreach (MessageDescription m
in od
.Messages
) {
204 bool isReq
= m
.Direction
== MessageDirection
.Input ^ isCallback
;
212 new ClientOperation (proxy
, od
.Name
, reqA
) :
213 new ClientOperation (proxy
, od
.Name
, reqA
, resA
);
214 foreach (MessageDescription md
in od
.Messages
) {
215 bool isReq
= md
.Direction
== MessageDirection
.Input ^ isCallback
;
217 md
.Body
.Parts
.Count
== 1 &&
218 md
.Body
.Parts
[0].Type
== typeof (Message
))
219 o
.SerializeRequest
= false;
221 md
.Body
.ReturnValue
!= null &&
222 md
.Body
.ReturnValue
.Type
== typeof (Message
))
223 o
.DeserializeReply
= false;
225 foreach (var fd
in od
.Faults
)
226 o
.FaultContractInfos
.Add (new FaultContractInfo (fd
.Action
, fd
.DetailType
));
228 // FIXME: at initialization time it does not seem to
229 // fill default formatter. It should be filled after
230 // applying all behaviors. (Tthat causes regression, so
231 // I don't care little compatibility difference so far)
233 // FIXME: pass correct isRpc, isEncoded
234 o
.Formatter
= new OperationFormatter (od
, false, false);
236 proxy
.Operations
.Add (o
);