// (C) Patrik Torstensson
//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
using System;
using System.Collections;
using System.IO;
}
internal class CADObjRef {
- public ObjRef objref;
+ ObjRef objref;
+ public int SourceDomain;
- public CADObjRef (ObjRef o) {
- this.objref = o;
+ public CADObjRef (ObjRef o, int sourceDomain) {
+ objref = o;
+ SourceDomain = sourceDomain;
+ }
+
+ public string TypeName {
+ get { return objref.TypeInfo.TypeName; }
+ }
+
+ public string URI {
+ get { return objref.URI; }
}
}
internal class CADMessageBase {
+ protected object [] _args;
+ protected byte [] _serializedArgs = null;
+ protected int _propertyCount = 0;
+ protected CADArgHolder _callContext;
+
// Helper to marshal properties
internal static int MarshalProperties (IDictionary dict, ref ArrayList args) {
IDictionary serDict = dict;
if (objType.IsPrimitive || objType == typeof(void))
return true;
+ if (objType.IsArray && objType.GetElementType().IsPrimitive && ((Array)obj).Rank == 1)
+ return true;
+
+ if (obj is string || obj is DateTime || obj is TimeSpan)
+ return true;
+
return false;
}
// Checks an argument if it's possible to pass without marshalling and
// if not it will be added to arguments to be serialized
- protected static object MarshalArgument (object arg, ref ArrayList args) {
+ protected object MarshalArgument (object arg, ref ArrayList args) {
if (null == arg)
return null;
if (IsPossibleToIgnoreMarshal (arg))
return arg;
-/* FIXME
- IsPossibleToCAD always return false.
- Avoid unneeded marshalling until IsPossibleToCAD is fixed
-
MarshalByRefObject mbr = arg as MarshalByRefObject;
- if (null != mbr) {
- if (!RemotingServices.IsTransparentProxy(mbr) || RemotingServices.GetRealProxy(mbr) is RemotingProxy) {
+ if (null != mbr)
+ {
+ if (RemotingServices.IsTransparentProxy(mbr)) {
+ // We don't deal with this case yet
+ }
+ else {
ObjRef objRef = RemotingServices.Marshal(mbr);
-
- // we should check if we can move this..
- if (objRef.IsPossibleToCAD ()) {
- return new CADObjRef(new ObjRef(objRef, true));
- }
+ return new CADObjRef(objRef, System.Threading.Thread.GetDomainID());
}
}
-*/
+
if (null == args)
args = new ArrayList();
return new CADArgHolder(args.Count - 1);
}
- protected static object UnmarshalArgument (object arg, ArrayList args) {
+ protected object UnmarshalArgument (object arg, ArrayList args) {
+ if (arg == null) return null;
+
// Check if argument is an holder (then we know that it's a serialized argument)
CADArgHolder holder = arg as CADArgHolder;
if (null != holder) {
CADObjRef objref = arg as CADObjRef;
if (null != objref) {
- return objref.objref.GetRealObject (new StreamingContext (StreamingContextStates.Other));
+ string typeName = string.Copy (objref.TypeName);
+ string uri = string.Copy (objref.URI);
+ int domid = objref.SourceDomain;
+
+ ChannelInfo cinfo = new ChannelInfo (new CrossAppDomainData (domid));
+ ObjRef localRef = new ObjRef (typeName, uri, cinfo);
+ return RemotingServices.Unmarshal (localRef);
+ }
+
+ if (arg is Array)
+ {
+ Array argb = (Array)arg;
+ Array argn;
+
+ // We can't use Array.CreateInstance (arg.GetType().GetElementType()) because
+ // GetElementType() returns a type from the source domain.
+
+ switch (Type.GetTypeCode (arg.GetType().GetElementType()))
+ {
+ case TypeCode.Boolean: argn = new bool [argb.Length]; break;
+ case TypeCode.Byte: argn = new Byte [argb.Length]; break;
+ case TypeCode.Char: argn = new Char [argb.Length]; break;
+ case TypeCode.Decimal: argn = new Decimal [argb.Length]; break;
+ case TypeCode.Double: argn = new Double [argb.Length]; break;
+ case TypeCode.Int16: argn = new Int16 [argb.Length]; break;
+ case TypeCode.Int32: argn = new Int32 [argb.Length]; break;
+ case TypeCode.Int64: argn = new Int64 [argb.Length]; break;
+ case TypeCode.SByte: argn = new SByte [argb.Length]; break;
+ case TypeCode.Single: argn = new Single [argb.Length]; break;
+ case TypeCode.UInt16: argn = new UInt16 [argb.Length]; break;
+ case TypeCode.UInt32: argn = new UInt32 [argb.Length]; break;
+ case TypeCode.UInt64: argn = new UInt64 [argb.Length]; break;
+ default: throw new NotSupportedException ();
+ }
+
+ argb.CopyTo (argn, 0);
+ return argn;
}
- // otherwise the argument is ok just to return
- return arg;
+ switch (Type.GetTypeCode (arg.GetType()))
+ {
+ case TypeCode.Boolean: return (bool)arg;
+ case TypeCode.Byte: return (byte)arg;
+ case TypeCode.Char: return (char)arg;
+ case TypeCode.Decimal: return (decimal)arg;
+ case TypeCode.Double: return (double)arg;
+ case TypeCode.Int16: return (Int16)arg;
+ case TypeCode.Int32: return (Int32)arg;
+ case TypeCode.Int64: return (Int64)arg;
+ case TypeCode.SByte: return (SByte)arg;
+ case TypeCode.Single: return (Single)arg;
+ case TypeCode.UInt16: return (UInt16)arg;
+ case TypeCode.UInt32: return (UInt32)arg;
+ case TypeCode.UInt64: return (UInt64)arg;
+ case TypeCode.String: return string.Copy ((string) arg);
+ case TypeCode.DateTime: return new DateTime (((DateTime)arg).Ticks);
+ default:
+ if (arg is TimeSpan) return new TimeSpan (((TimeSpan)arg).Ticks);
+ break;
+ }
+
+ throw new NotSupportedException ("Parameter of type " + arg.GetType () + " cannot be unmarshalled");
}
- internal static object [] MarshalArguments (object [] arguments, ref ArrayList args) {
+ internal object [] MarshalArguments (object [] arguments, ref ArrayList args) {
object [] marshalledArgs = new object [arguments.Length];
int total = arguments.Length;
return marshalledArgs;
}
- internal static object [] UnmarshalArguments (object [] arguments, ArrayList args) {
+ internal object [] UnmarshalArguments (object [] arguments, ArrayList args) {
object [] unmarshalledArgs = new object [arguments.Length];
int total = arguments.Length;
return unmarshalledArgs;
}
+
+ protected void SaveLogicalCallContext (IMethodMessage msg, ref ArrayList serializeList)
+ {
+ if (msg.LogicalCallContext != null && msg.LogicalCallContext.HasInfo)
+ {
+ if (serializeList == null)
+ serializeList = new ArrayList();
+
+ _callContext = new CADArgHolder (serializeList.Count);
+ serializeList.Add (msg.LogicalCallContext);
+ }
+ }
+
+ internal LogicalCallContext GetLogicalCallContext (ArrayList args)
+ {
+ if (null == _callContext)
+ return null;
+
+ return (LogicalCallContext) args [_callContext.index];
+ }
}
// Used when passing a IMethodCallMessage between appdomains
internal class CADMethodCallMessage : CADMessageBase {
string _uri;
- string _methodName;
- string _typeName;
- object [] _args;
-
- byte [] _serializedArgs = null;
-
- CADArgHolder _methodSignature;
- CADArgHolder _callContext;
-
- int _propertyCount = 0;
-
- internal string TypeName {
- get {
- return _typeName;
- }
- }
-
+
+ internal RuntimeMethodHandle MethodHandle;
+
internal string Uri {
get {
return _uri;
}
}
- internal string MethodName {
- get {
- return _methodName;
- }
- }
-
static internal CADMethodCallMessage Create (IMessage callMsg) {
IMethodCallMessage msg = callMsg as IMethodCallMessage;
if (null == msg)
return new CADMethodCallMessage (msg);
}
- // todo
internal CADMethodCallMessage (IMethodCallMessage callMsg) {
- _methodName = callMsg.MethodName;
- _typeName = callMsg.TypeName;
_uri = callMsg.Uri;
+ MethodHandle = callMsg.MethodBase.MethodHandle;
ArrayList serializeList = null;
_args = MarshalArguments ( callMsg.Args, ref serializeList);
- // check if we need to save method signature
- if (RemotingServices.IsMethodOverloaded (callMsg)) {
- if (null == serializeList)
- serializeList = new ArrayList();
-
- _methodSignature = new CADArgHolder (serializeList.Count);
- serializeList.Add(callMsg.MethodSignature);
- }
-
- // todo: save callcontext
+ // Save callcontext
+ SaveLogicalCallContext (callMsg, ref serializeList);
+
+ // Serialize message data if needed
if (null != serializeList) {
- MemoryStream stm = CADSerializer.SerializeObject (serializeList);
+ MemoryStream stm = CADSerializer.SerializeObject (serializeList.ToArray());
_serializedArgs = stm.GetBuffer();
}
}
ArrayList ret = null;
if (null != _serializedArgs) {
- ret = (ArrayList) CADSerializer.DeserializeObject (new MemoryStream (_serializedArgs));
+ object[] oret = (object[]) CADSerializer.DeserializeObject (new MemoryStream (_serializedArgs));
+ ret = new ArrayList (oret);
_serializedArgs = null;
}
internal object [] GetArgs (ArrayList args) {
return UnmarshalArguments (_args, args);
}
-
- internal object [] GetMethodSignature (ArrayList args) {
- if (null == _methodSignature)
- return null;
-
- return (object []) args [_methodSignature.index];
- }
internal int PropertiesCount {
get {
// Used when passing a IMethodReturnMessage between appdomains
internal class CADMethodReturnMessage : CADMessageBase {
- object [] _args;
object _returnValue;
-
- byte [] _serializedArgs = null;
-
CADArgHolder _exception = null;
- CADArgHolder _callContext;
-
- int _propertyCount = 0;
static internal CADMethodReturnMessage Create (IMessage callMsg) {
IMethodReturnMessage msg = callMsg as IMethodReturnMessage;
serializeList.Add(retMsg.Exception);
}
- // todo: save callcontext
+ // Save callcontext
+ SaveLogicalCallContext (retMsg, ref serializeList);
if (null != serializeList) {
- MemoryStream stm = CADSerializer.SerializeObject (serializeList);
+ MemoryStream stm = CADSerializer.SerializeObject (serializeList.ToArray());
_serializedArgs = stm.GetBuffer();
}
}
ArrayList ret = null;
if (null != _serializedArgs) {
- ret = (ArrayList) CADSerializer.DeserializeObject (new MemoryStream (_serializedArgs));
+ object[] oret = (object[]) CADSerializer.DeserializeObject (new MemoryStream (_serializedArgs));
+ ret = new ArrayList (oret);
_serializedArgs = null;
}