Merge pull request #4967 from kumpera/profiler-arg-cleanup
[mono.git] / mcs / class / corlib / System.Runtime.Remoting.Messaging / CADMessages.cs
index 2d1931c3d5379565879664d8fa25b56ff7f7c57f..4d20d6a67879155c1e8b32c91548f97ef55cede0 100644 (file)
@@ -51,14 +51,16 @@ namespace System.Runtime.Remoting.Messaging {
        }
        
        internal class CADObjRef {
-               ObjRef objref;
-               public int SourceDomain;
+               internal ObjRef objref;
+               internal int SourceDomain;
+               internal byte[] TypeInfo;
 
                public CADObjRef (ObjRef o, int sourceDomain) {
                        objref = o;
+                       TypeInfo = o.SerializeType ();
                        SourceDomain = sourceDomain;
                }
-               
+
                public string TypeName {
                        get { return objref.TypeInfo.TypeName; }
                }
@@ -68,22 +70,109 @@ namespace System.Runtime.Remoting.Messaging {
                }
        }
 
+       [Serializable]
+       internal class CADMethodRef
+       {
+               Type[] GetTypes (string[] typeArray)
+               {
+                       Type[] res = new Type [typeArray.Length];
+                       for (int i = 0; i < typeArray.Length; ++i)
+                               res [i] = Type.GetType (typeArray [i], true);
+                       return res;
+               }
+
+               bool ctor;
+               string typeName;
+               string methodName;
+               string[] param_names;
+               string[] generic_arg_names;
+
+               public MethodBase Resolve ()
+               {
+                       Type type = Type.GetType (typeName, true);
+                       MethodBase sig_cand = null;
+                       Type[] param_types = GetTypes (param_names);
+                       if (ctor)
+                               sig_cand = type.GetConstructor (BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance, null, param_types, null);
+                       else
+                               sig_cand = type.GetMethod (methodName, BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance, null, param_types, null);
+
+                       if (sig_cand != null && generic_arg_names != null)
+                               sig_cand = ((MethodInfo)sig_cand).MakeGenericMethod (GetTypes (generic_arg_names));
+
+                       if (sig_cand == null)
+                               throw new RemotingException ($"Method '{methodName}' not found in type '{typeName}'");
+
+                       return sig_cand;
+               }
+
+               public CADMethodRef (IMethodMessage msg)
+               {
+                       MethodBase method = msg.MethodBase;
+                       typeName = method.DeclaringType.AssemblyQualifiedName;
+                       ctor = method.IsConstructor;
+                       methodName = method.Name;
+
+                       if (!ctor && method.IsGenericMethod) {
+                               var ga = method.GetGenericArguments ();
+                               generic_arg_names = new string [ga.Length];
+                               for (int i = 0; i < ga.Length; ++i)
+                                       generic_arg_names [i] = ga [i].AssemblyQualifiedName;
+
+                               method = ((MethodInfo)method).GetGenericMethodDefinition ();
+                       }
+
+                       var param_types = method.GetParameters ();
+                       param_names = new string [param_types.Length];
+                       for (int i = 0; i < param_types.Length; ++i)
+                               param_names [i] = param_types [i].ParameterType.AssemblyQualifiedName;
+               }
+       }
+
        internal class CADMessageBase {
 
                protected object [] _args;
                protected byte [] _serializedArgs = null;
                protected int _propertyCount = 0;
                protected CADArgHolder _callContext;
-               
+               internal byte[] serializedMethod;
+
+               public CADMessageBase (IMethodMessage msg) {
+                       CADMethodRef methodRef = new CADMethodRef (msg);
+                       serializedMethod = CADSerializer.SerializeObject (methodRef).GetBuffer ();
+               }
+
+               internal MethodBase GetMethod ()
+               {
+                       CADMethodRef methRef = (CADMethodRef)CADSerializer.DeserializeObjectSafe (serializedMethod);
+
+                       return methRef.Resolve ();
+               }
+
+               static protected Type [] GetSignature (MethodBase methodBase, bool load)
+               {
+                       ParameterInfo[] pars = methodBase.GetParameters ();
+                       Type[] signature = new Type [pars.Length];
+                       for (int n=0; n<pars.Length; n++) {
+                               // The parameter types may also be loaded from a different assembly, so we need
+                               // to load them again
+                               if (load)
+                                       signature [n] = Type.GetType (pars [n].ParameterType.AssemblyQualifiedName, true);
+                               else
+                                       signature [n] = pars [n].ParameterType;
+                       }
+                       return signature;
+               }
+
                // Helper to marshal properties
                internal static int MarshalProperties (IDictionary dict, ref ArrayList args) {
                        IDictionary serDict = dict;
                        int count = 0;
 
-                       MethodDictionary msgDict = dict as MethodDictionary;
+                       MessageDictionary msgDict = dict as MessageDictionary;
                        if (null != msgDict) {
-                               if (msgDict.HasInternalProperties) {
-                                       serDict = msgDict.InternalProperties;
+                               if (msgDict.HasUserData ()) {
+                                       serDict = msgDict.InternalDictionary;
                                        if (null != serDict) {
                                                foreach (DictionaryEntry e in serDict) {
                                                        if (null == args)
@@ -171,12 +260,7 @@ namespace System.Runtime.Remoting.Messaging {
 
                        CADObjRef objref = arg as CADObjRef;
                        if (null != objref) {
-                               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);
+                               ObjRef localRef = objref.objref.DeserializeInTheCurrentDomain (objref.SourceDomain, objref.TypeInfo);
                                return RemotingServices.Unmarshal (localRef);
                        }
                        
@@ -255,7 +339,7 @@ namespace System.Runtime.Remoting.Messaging {
 
                        return unmarshalledArgs;
                }
-               
+
                protected void SaveLogicalCallContext (IMethodMessage msg, ref ArrayList serializeList)
                {
                        if (msg.LogicalCallContext != null && msg.LogicalCallContext.HasInfo) 
@@ -280,10 +364,7 @@ namespace System.Runtime.Remoting.Messaging {
        // Used when passing a IMethodCallMessage between appdomains
        internal class CADMethodCallMessage : CADMessageBase {
                string _uri;
-               
-               internal RuntimeMethodHandle MethodHandle;
-               internal string FullTypeName;
-               
+
                internal string Uri {
                        get {
                                return _uri;
@@ -298,10 +379,8 @@ namespace System.Runtime.Remoting.Messaging {
                        return new CADMethodCallMessage (msg);
                }
 
-               internal CADMethodCallMessage (IMethodCallMessage callMsg) {
+               internal CADMethodCallMessage (IMethodCallMessage callMsg): base (callMsg) {
                        _uri = callMsg.Uri;
-                       MethodHandle = callMsg.MethodBase.MethodHandle;
-                       FullTypeName = callMsg.MethodBase.DeclaringType.AssemblyQualifiedName;
 
                        ArrayList serializeList = null; 
                        
@@ -342,34 +421,15 @@ namespace System.Runtime.Remoting.Messaging {
                        }
                }
                
-               internal MethodBase GetMethod ()
-               {
-                       MethodBase methodBase = MethodBase.GetMethodFromHandle (MethodHandle);
-                       Type tt = Type.GetType (FullTypeName);
-                       
-                       if (tt != methodBase.DeclaringType) {
-                               // The target domain has loaded the type from a different assembly.
-                               // We need to locate the correct type and get the method from it
-                               ParameterInfo[] pars = methodBase.GetParameters ();
-                               Type[] signature = new Type [pars.Length];
-                               for (int n=0; n<pars.Length; n++) {
-                                       // The parameter types may also be loaded from a different assembly, so we need
-                                       // to load them again
-                                       signature [n] = Type.GetType (pars [n].ParameterType.AssemblyQualifiedName, true);
-                               }
-                               MethodBase mb = tt.GetMethod (methodBase.Name, BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance, null, signature, null);
-                               if (mb == null)
-                                       throw new RemotingException ("Method '" + methodBase.Name + "' not found in type '" + tt + "'");
-                               return mb;
-                       }
-                       return methodBase;
-               }
        }
        
        // Used when passing a IMethodReturnMessage between appdomains
        internal class CADMethodReturnMessage : CADMessageBase {
                object _returnValue;
                CADArgHolder _exception = null;
+#pragma warning disable 414
+               Type [] _sig;
+#pragma warning restore
 
                static internal CADMethodReturnMessage Create (IMessage callMsg) {
                        IMethodReturnMessage msg = callMsg as IMethodReturnMessage;
@@ -379,7 +439,7 @@ namespace System.Runtime.Remoting.Messaging {
                        return new CADMethodReturnMessage (msg);
                }
 
-               internal CADMethodReturnMessage(IMethodReturnMessage retMsg) {
+               internal CADMethodReturnMessage(IMethodReturnMessage retMsg): base (retMsg) {
                        ArrayList serializeList = null; 
                        
                        _propertyCount = MarshalProperties (retMsg.Properties, ref serializeList);
@@ -387,6 +447,8 @@ namespace System.Runtime.Remoting.Messaging {
                        _returnValue = MarshalArgument ( retMsg.ReturnValue, ref serializeList);
                        _args = MarshalArguments ( retMsg.Args, ref serializeList);
 
+                       _sig = GetSignature (GetMethod (), true);
+
                        if (null != retMsg.Exception) {
                                if (null == serializeList)
                                        serializeList = new ArrayList();
@@ -419,7 +481,7 @@ namespace System.Runtime.Remoting.Messaging {
                internal object [] GetArgs (ArrayList args) {
                        return UnmarshalArguments (_args, args);
                }
-                       
+
                internal object GetReturnValue (ArrayList args) {
                        return UnmarshalArgument (_returnValue, args);
                }