2 // System.Runtime.Remoting.Messaging.CADMessages.cs
7 // (C) Patrik Torstensson
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
;
36 using System
.Runtime
.Serialization
;
37 using System
.Runtime
.Remoting
;
38 using System
.Runtime
.Remoting
.Channels
;
39 using System
.Runtime
.Remoting
.Messaging
;
40 using System
.Runtime
.Remoting
.Proxies
;
42 namespace System
.Runtime
.Remoting
.Messaging
{
44 internal class CADArgHolder
{
47 public CADArgHolder (int i
) {
52 internal class CADObjRef
{
54 public int SourceDomain
;
56 public CADObjRef (ObjRef o
, int sourceDomain
) {
58 SourceDomain
= sourceDomain
;
61 public string TypeName
{
62 get { return objref.TypeInfo.TypeName; }
66 get { return objref.URI; }
70 internal class CADMessageBase
{
72 protected object [] _args
;
73 protected byte [] _serializedArgs
= null;
74 protected int _propertyCount
= 0;
75 protected CADArgHolder _callContext
;
77 // Helper to marshal properties
78 internal static int MarshalProperties (IDictionary dict
, ref ArrayList args
) {
79 IDictionary serDict
= dict
;
82 MethodDictionary msgDict
= dict
as MethodDictionary
;
83 if (null != msgDict
) {
84 if (msgDict
.HasInternalProperties
) {
85 serDict
= msgDict
.InternalProperties
;
86 if (null != serDict
) {
87 foreach (DictionaryEntry e
in serDict
) {
89 args
= new ArrayList();
97 foreach (DictionaryEntry e
in serDict
) {
99 args
= new ArrayList();
109 internal static void UnmarshalProperties (IDictionary dict
, int count
, ArrayList args
) {
110 for (int i
= 0; i
< count
; i
++) {
111 DictionaryEntry e
= (DictionaryEntry
) args
[i
];
112 dict
[e
.Key
] = e
.Value
;
116 // We can ignore marshalling for string and primitive types
117 private static bool IsPossibleToIgnoreMarshal (object obj
) {
119 Type objType
= obj
.GetType();
120 if (objType
.IsPrimitive
|| objType
== typeof(void))
123 if (objType
.IsArray
&& objType
.GetElementType().IsPrimitive
&& ((Array
)obj
).Rank
== 1)
126 if (obj
is string || obj
is DateTime
|| obj
is TimeSpan
)
132 // Checks an argument if it's possible to pass without marshalling and
133 // if not it will be added to arguments to be serialized
134 protected object MarshalArgument (object arg
, ref ArrayList args
) {
138 if (IsPossibleToIgnoreMarshal (arg
))
141 MarshalByRefObject mbr
= arg
as MarshalByRefObject
;
144 if (RemotingServices
.IsTransparentProxy(mbr
)) {
145 // We don't deal with this case yet
148 ObjRef objRef
= RemotingServices
.Marshal(mbr
);
149 return new CADObjRef(objRef
, System
.Threading
.Thread
.GetDomainID());
154 args
= new ArrayList();
158 // return position that the arg exists in the serialized list
159 return new CADArgHolder(args
.Count
- 1);
162 protected object UnmarshalArgument (object arg
, ArrayList args
) {
163 if (arg
== null) return null;
165 // Check if argument is an holder (then we know that it's a serialized argument)
166 CADArgHolder holder
= arg
as CADArgHolder
;
167 if (null != holder
) {
168 return args
[holder
.index
];
171 CADObjRef objref
= arg
as CADObjRef
;
172 if (null != objref
) {
173 string typeName
= string.Copy (objref
.TypeName
);
174 string uri
= string.Copy (objref
.URI
);
175 int domid
= objref
.SourceDomain
;
177 ChannelInfo cinfo
= new ChannelInfo (new CrossAppDomainData (domid
));
178 ObjRef localRef
= new ObjRef (typeName
, uri
, cinfo
);
179 return RemotingServices
.Unmarshal (localRef
);
184 Array argb
= (Array
)arg
;
187 // We can't use Array.CreateInstance (arg.GetType().GetElementType()) because
188 // GetElementType() returns a type from the source domain.
190 switch (Type
.GetTypeCode (arg
.GetType().GetElementType()))
192 case TypeCode
.Boolean
: argn
= new bool [argb
.Length
]; break;
193 case TypeCode
.Byte
: argn
= new Byte
[argb
.Length
]; break;
194 case TypeCode
.Char
: argn
= new Char
[argb
.Length
]; break;
195 case TypeCode
.Decimal
: argn
= new Decimal
[argb
.Length
]; break;
196 case TypeCode
.Double
: argn
= new Double
[argb
.Length
]; break;
197 case TypeCode
.Int16
: argn
= new Int16
[argb
.Length
]; break;
198 case TypeCode
.Int32
: argn
= new Int32
[argb
.Length
]; break;
199 case TypeCode
.Int64
: argn
= new Int64
[argb
.Length
]; break;
200 case TypeCode
.SByte
: argn
= new SByte
[argb
.Length
]; break;
201 case TypeCode
.Single
: argn
= new Single
[argb
.Length
]; break;
202 case TypeCode
.UInt16
: argn
= new UInt16
[argb
.Length
]; break;
203 case TypeCode
.UInt32
: argn
= new UInt32
[argb
.Length
]; break;
204 case TypeCode
.UInt64
: argn
= new UInt64
[argb
.Length
]; break;
205 default: throw new NotSupportedException ();
208 argb
.CopyTo (argn
, 0);
212 switch (Type
.GetTypeCode (arg
.GetType()))
214 case TypeCode
.Boolean
: return (bool)arg
;
215 case TypeCode
.Byte
: return (byte)arg
;
216 case TypeCode
.Char
: return (char)arg
;
217 case TypeCode
.Decimal
: return (decimal)arg
;
218 case TypeCode
.Double
: return (double)arg
;
219 case TypeCode
.Int16
: return (Int16
)arg
;
220 case TypeCode
.Int32
: return (Int32
)arg
;
221 case TypeCode
.Int64
: return (Int64
)arg
;
222 case TypeCode
.SByte
: return (SByte
)arg
;
223 case TypeCode
.Single
: return (Single
)arg
;
224 case TypeCode
.UInt16
: return (UInt16
)arg
;
225 case TypeCode
.UInt32
: return (UInt32
)arg
;
226 case TypeCode
.UInt64
: return (UInt64
)arg
;
227 case TypeCode
.String
: return string.Copy ((string) arg
);
228 case TypeCode
.DateTime
: return new DateTime (((DateTime
)arg
).Ticks
);
230 if (arg
is TimeSpan
) return new TimeSpan (((TimeSpan
)arg
).Ticks
);
234 throw new NotSupportedException ("Parameter of type " + arg
.GetType () + " cannot be unmarshalled");
237 internal object [] MarshalArguments (object [] arguments
, ref ArrayList args
) {
238 object [] marshalledArgs
= new object [arguments
.Length
];
240 int total
= arguments
.Length
;
241 for (int i
= 0; i
< total
; i
++)
242 marshalledArgs
[i
] = MarshalArgument (arguments
[i
], ref args
);
244 return marshalledArgs
;
247 internal object [] UnmarshalArguments (object [] arguments
, ArrayList args
) {
248 object [] unmarshalledArgs
= new object [arguments
.Length
];
250 int total
= arguments
.Length
;
251 for (int i
= 0; i
< total
; i
++)
252 unmarshalledArgs
[i
] = UnmarshalArgument (arguments
[i
], args
);
254 return unmarshalledArgs
;
257 protected void SaveLogicalCallContext (IMethodMessage msg
, ref ArrayList serializeList
)
259 if (msg
.LogicalCallContext
!= null && msg
.LogicalCallContext
.HasInfo
)
261 if (serializeList
== null)
262 serializeList
= new ArrayList();
264 _callContext
= new CADArgHolder (serializeList
.Count
);
265 serializeList
.Add (msg
.LogicalCallContext
);
269 internal LogicalCallContext
GetLogicalCallContext (ArrayList args
)
271 if (null == _callContext
)
274 return (LogicalCallContext
) args
[_callContext
.index
];
278 // Used when passing a IMethodCallMessage between appdomains
279 internal class CADMethodCallMessage
: CADMessageBase
{
282 internal RuntimeMethodHandle MethodHandle
;
284 internal string Uri
{
290 static internal CADMethodCallMessage
Create (IMessage callMsg
) {
291 IMethodCallMessage msg
= callMsg
as IMethodCallMessage
;
295 return new CADMethodCallMessage (msg
);
298 internal CADMethodCallMessage (IMethodCallMessage callMsg
) {
300 MethodHandle
= callMsg
.MethodBase
.MethodHandle
;
302 ArrayList serializeList
= null;
304 _propertyCount
= MarshalProperties (callMsg
.Properties
, ref serializeList
);
306 _args
= MarshalArguments ( callMsg
.Args
, ref serializeList
);
309 SaveLogicalCallContext (callMsg
, ref serializeList
);
311 // Serialize message data if needed
313 if (null != serializeList
) {
314 MemoryStream stm
= CADSerializer
.SerializeObject (serializeList
.ToArray());
315 _serializedArgs
= stm
.GetBuffer();
319 internal ArrayList
GetArguments () {
320 ArrayList ret
= null;
322 if (null != _serializedArgs
) {
323 object[] oret
= (object[]) CADSerializer
.DeserializeObject (new MemoryStream (_serializedArgs
));
324 ret
= new ArrayList (oret
);
325 _serializedArgs
= null;
331 internal object [] GetArgs (ArrayList args
) {
332 return UnmarshalArguments (_args
, args
);
335 internal int PropertiesCount
{
337 return _propertyCount
;
342 // Used when passing a IMethodReturnMessage between appdomains
343 internal class CADMethodReturnMessage
: CADMessageBase
{
345 CADArgHolder _exception
= null;
347 static internal CADMethodReturnMessage
Create (IMessage callMsg
) {
348 IMethodReturnMessage msg
= callMsg
as IMethodReturnMessage
;
352 return new CADMethodReturnMessage (msg
);
355 internal CADMethodReturnMessage(IMethodReturnMessage retMsg
) {
356 ArrayList serializeList
= null;
358 _propertyCount
= MarshalProperties (retMsg
.Properties
, ref serializeList
);
360 _returnValue
= MarshalArgument ( retMsg
.ReturnValue
, ref serializeList
);
361 _args
= MarshalArguments ( retMsg
.Args
, ref serializeList
);
363 if (null != retMsg
.Exception
) {
364 if (null == serializeList
)
365 serializeList
= new ArrayList();
367 _exception
= new CADArgHolder (serializeList
.Count
);
368 serializeList
.Add(retMsg
.Exception
);
372 SaveLogicalCallContext (retMsg
, ref serializeList
);
374 if (null != serializeList
) {
375 MemoryStream stm
= CADSerializer
.SerializeObject (serializeList
.ToArray());
376 _serializedArgs
= stm
.GetBuffer();
380 internal ArrayList
GetArguments () {
381 ArrayList ret
= null;
383 if (null != _serializedArgs
) {
384 object[] oret
= (object[]) CADSerializer
.DeserializeObject (new MemoryStream (_serializedArgs
));
385 ret
= new ArrayList (oret
);
386 _serializedArgs
= null;
392 internal object [] GetArgs (ArrayList args
) {
393 return UnmarshalArguments (_args
, args
);
396 internal object GetReturnValue (ArrayList args
) {
397 return UnmarshalArgument (_returnValue
, args
);
400 internal Exception
GetException(ArrayList args
) {
401 if (null == _exception
)
404 return (Exception
) args
[_exception
.index
];
407 internal int PropertiesCount
{
409 return _propertyCount
;