2 // System.Runtime.Remoting.Messaging.MethodCall.cs
4 // Author: Duncan Mak (duncan@ximian.com)
5 // Lluis Sanchez Gual (lluis@ideary.com)
7 // 2002 (C) Copyright, Ximian, Inc.
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System
.Collections
;
35 using System
.Reflection
;
36 using System
.Runtime
.Serialization
;
38 namespace System
.Runtime
.Remoting
.Messaging
{
40 [Serializable
] [CLSCompliant (false)]
41 public class MethodCall
: IMethodCallMessage
, IMethodMessage
, IMessage
, ISerializable
, IInternalMessage
, ISerializationRootObject
47 Type
[] _methodSignature
;
48 MethodBase _methodBase
;
49 LogicalCallContext _callContext
;
51 Identity _targetIdentity
;
53 protected IDictionary ExternalProperties
;
54 protected IDictionary InternalProperties
;
56 public MethodCall (Header
[] headers
)
60 if (headers
== null || headers
.Length
== 0) return;
62 foreach (Header header
in headers
)
63 InitMethodProperty (header
.Name
, header
.Value
);
68 internal MethodCall (SerializationInfo info
, StreamingContext context
)
72 foreach (SerializationEntry entry
in info
)
73 InitMethodProperty ((string)entry
.Name
, entry
.Value
);
76 internal MethodCall (CADMethodCallMessage msg
)
78 _uri
= string.Copy (msg
.Uri
);
80 // Get unmarshalled arguments
81 ArrayList args
= msg
.GetArguments ();
83 _args
= msg
.GetArgs (args
);
84 _callContext
= msg
.GetLogicalCallContext (args
);
85 if (_callContext
== null)
86 _callContext
= new LogicalCallContext ();
88 _methodBase
= MethodBase
.GetMethodFromHandle (msg
.MethodHandle
);
91 if (msg
.PropertiesCount
> 0)
92 CADMessageBase
.UnmarshalProperties (Properties
, msg
.PropertiesCount
, args
);
95 public MethodCall (IMessage msg
)
97 if (msg
is IMethodMessage
)
98 CopyFrom ((IMethodMessage
) msg
);
101 IDictionary dic
= msg
.Properties
;
102 foreach (DictionaryEntry entry
in msg
.Properties
)
103 InitMethodProperty ((String
) entry
.Key
, entry
.Value
);
108 internal MethodCall (string uri
, string typeName
, string methodName
, object[] args
)
111 _typeName
= typeName
;
112 _methodName
= methodName
;
119 internal MethodCall ()
123 internal void CopyFrom (IMethodMessage call
)
126 _typeName
= call
.TypeName
;
127 _methodName
= call
.MethodName
;
129 _methodSignature
= (Type
[]) call
.MethodSignature
;
130 _methodBase
= call
.MethodBase
;
131 _callContext
= call
.LogicalCallContext
;
136 internal virtual void InitMethodProperty(string key
, object value)
140 case "__TypeName" : _typeName
= (string) value; return;
141 case "__MethodName" : _methodName
= (string) value; return;
142 case "__MethodSignature" : _methodSignature
= (Type
[]) value; return;
143 case "__Args" : _args
= (object[]) value; return;
144 case "__CallContext" : _callContext
= (LogicalCallContext
) value; return;
145 case "__Uri" : _uri
= (string) value; return;
146 default: Properties
[key
] = value; return;
150 public virtual void GetObjectData (SerializationInfo info
, StreamingContext context
)
152 info
.AddValue ("__TypeName", _typeName
);
153 info
.AddValue ("__MethodName", _methodName
);
154 info
.AddValue ("__MethodSignature", _methodSignature
);
155 info
.AddValue ("__Args", _args
);
156 info
.AddValue ("__CallContext", _callContext
);
157 info
.AddValue ("__Uri", _uri
);
159 if (InternalProperties
!= null) {
160 foreach (DictionaryEntry entry
in InternalProperties
)
161 info
.AddValue ((string) entry
.Key
, entry
.Value
);
165 public int ArgCount
{
166 get { return _args.Length; }
169 public object[] Args
{
170 get { return _args; }
173 public bool HasVarArgs
{
174 get { return (MethodBase.CallingConvention | CallingConventions.VarArgs) != 0; }
177 public int InArgCount
181 if (_inArgInfo
== null) _inArgInfo
= new ArgInfo (_methodBase
, ArgInfoType
.In
);
182 return _inArgInfo
.GetInOutArgCount();
186 public object[] InArgs
190 if (_inArgInfo
== null) _inArgInfo
= new ArgInfo (_methodBase
, ArgInfoType
.In
);
191 return _inArgInfo
.GetInOutArgs (_args
);
195 public LogicalCallContext LogicalCallContext
{
196 get { return _callContext; }
199 public MethodBase MethodBase
{
201 if (_methodBase
== null)
208 public string MethodName
{
210 // lazily fill in _methodName from _methodBase
211 if (_methodName
== null)
212 _methodName
= _methodBase
.Name
;
217 public object MethodSignature
{
219 if (_methodSignature
== null && _methodBase
!= null)
221 ParameterInfo
[] parameters
= _methodBase
.GetParameters();
222 _methodSignature
= new Type
[parameters
.Length
];
223 for (int n
=0; n
<parameters
.Length
; n
++)
224 _methodSignature
[n
] = parameters
[n
].ParameterType
;
226 return _methodSignature
;
230 public virtual IDictionary Properties
{
233 if (ExternalProperties
== null) InitDictionary ();
234 return ExternalProperties
;
238 internal virtual void InitDictionary()
240 MethodCallDictionary props
= new MethodCallDictionary (this);
241 ExternalProperties
= props
;
242 InternalProperties
= props
.GetInternalProperties();
245 public string TypeName
248 // lazily fill in _typeName from _methodBase
249 if (_typeName
== null)
250 _typeName
= _methodBase
.DeclaringType
.AssemblyQualifiedName
;
257 set { _uri = value; }
260 public object GetArg (int argNum
)
262 return _args
[argNum
];
265 public string GetArgName (int index
)
267 return _methodBase
.GetParameters()[index
].Name
;
270 public object GetInArg (int argNum
)
272 if (_inArgInfo
== null) _inArgInfo
= new ArgInfo (_methodBase
, ArgInfoType
.In
);
273 return _args
[_inArgInfo
.GetInOutArgIndex (argNum
)];
276 public string GetInArgName (int index
)
278 if (_inArgInfo
== null) _inArgInfo
= new ArgInfo (_methodBase
, ArgInfoType
.In
);
279 return _inArgInfo
.GetInOutArgName(index
);
283 public virtual object HeaderHandler (Header
[] h
)
285 throw new NotImplementedException ();
288 public virtual void Init ()
292 public void ResolveMethod ()
296 Type type
= RemotingServices
.GetServerTypeForUri (_uri
);
297 if (type
== null) throw new RemotingException ("Requested service not found. No receiver for uri " + _uri
);
299 if (CanCastTo (_typeName
, type
)) {
300 _methodBase
= RemotingServices
.GetMethodBaseFromName (type
, _methodName
, _methodSignature
);
304 throw new RemotingException ("Cannot cast from client type '" + _typeName
+ "' to server type '" + type
.FullName
+ "'");
306 _methodBase
= RemotingServices
.GetMethodBaseFromMethodMessage (this);
309 bool CanCastTo (string clientType
, Type serverType
)
311 int i
= clientType
.IndexOf(',');
312 if (i
!= -1) clientType
= clientType
.Substring (0,i
).Trim();
314 if (clientType
== serverType
.FullName
) return true;
316 // base class hierarchy
318 Type baseType
= serverType
.BaseType
;
319 while (baseType
!= null) {
320 if (clientType
== baseType
.FullName
) return true;
321 baseType
= baseType
.BaseType
;
324 // Implemented interfaces
326 Type
[] interfaces
= serverType
.GetInterfaces();
327 foreach (Type itype
in interfaces
)
328 if (clientType
== itype
.FullName
) return true;
334 public void RootSetObjectData (SerializationInfo info
, StreamingContext context
)
336 throw new NotImplementedException ();
339 Identity IInternalMessage
.TargetIdentity
341 get { return _targetIdentity; }
342 set { _targetIdentity = value; }
345 public override string ToString ()
347 string s
= _typeName
.Split(',')[0] + "." + _methodName
+ " (";
348 Type
[] ts
= (Type
[]) MethodSignature
;
351 for (int n
=0; n
<_args
.Length
; n
++)
354 if (_args
[n
] != null) s
+= _args
[n
].GetType().Name
+ " ";
356 if (_args
[n
] != null) s
+= " = {" + _args[n] + "}";