2008-07-06 Andreas Nahr <ClassDevelopment@A-SoftTech.com>
[mono.git] / mcs / class / corlib / System.Runtime.Remoting.Messaging / MethodCall.cs
index a10e84d6638bbfcae4c0c734341aa749de188143..d925c7e909f87970a8a90ba53c7173724481dab8 100644 (file)
@@ -38,6 +38,9 @@ using System.Runtime.Serialization;
 namespace System.Runtime.Remoting.Messaging {
 
        [Serializable] [CLSCompliant (false)]
+#if NET_2_0
+       [System.Runtime.InteropServices.ComVisible (true)]
+#endif
        public class MethodCall : IMethodCallMessage, IMethodMessage, IMessage, ISerializable, IInternalMessage, ISerializationRootObject
        {
                string _uri;
@@ -49,17 +52,20 @@ namespace System.Runtime.Remoting.Messaging {
                LogicalCallContext _callContext;
                ArgInfo _inArgInfo;
                Identity _targetIdentity;
+#if NET_2_0
+               Type[] _genericArguments;
+#endif
 
                protected IDictionary ExternalProperties;
                protected IDictionary InternalProperties;
 
-               public MethodCall (Header [] headers)
+               public MethodCall (Header [] h1)
                {
                        Init();
 
-                       if (headers == null || headers.Length == 0) return;
+                       if (h1 == null || h1.Length == 0) return;
 
-                       foreach (Header header in headers)
+                       foreach (Header header in h1)
                                InitMethodProperty (header.Name, header.Value);
 
                        ResolveMethod ();
@@ -129,7 +135,6 @@ namespace System.Runtime.Remoting.Messaging {
                        _methodSignature = (Type[]) call.MethodSignature;
                        _methodBase = call.MethodBase;
                        _callContext = call.LogicalCallContext;
-
                        Init();
                }
                
@@ -143,6 +148,9 @@ namespace System.Runtime.Remoting.Messaging {
                                case "__Args" : _args = (object[]) value; return;
                                case "__CallContext" : _callContext = (LogicalCallContext) value; return;
                                case "__Uri" : _uri = (string) value; return;
+#if NET_2_0
+                               case "__GenericArguments" : _genericArguments = (Type[]) value; return;
+#endif
                                default: Properties[key] = value; return;
                        }
                }
@@ -155,6 +163,9 @@ namespace System.Runtime.Remoting.Messaging {
                        info.AddValue ("__Args", _args);
                        info.AddValue ("__CallContext", _callContext);
                        info.AddValue ("__Uri", _uri);
+#if NET_2_0
+                       info.AddValue ("__GenericArguments", _genericArguments);
+#endif
 
                        if (InternalProperties != null) {
                                foreach (DictionaryEntry entry in InternalProperties)
@@ -261,6 +272,11 @@ namespace System.Runtime.Remoting.Messaging {
                        set { _uri = value; }
                }
 
+               string IInternalMessage.Uri {
+                       get { return Uri; }
+                       set { Uri = value; }
+               }
+
                public object GetArg (int argNum)
                {
                        return _args[argNum];
@@ -303,32 +319,53 @@ namespace System.Runtime.Remoting.Messaging {
                                        throw new RemotingException ("Requested service not found" + sname + ". No receiver for uri " + _uri);
                                }
 
-                               if (CastTo (_typeName, type) != null) {
-                                       _methodBase = RemotingServices.GetMethodBaseFromName (type, _methodName, _methodSignature);
-                                       if (_methodBase == null) throw new RemotingException ("Method " + _methodName + " not found in " + type);
-                                       return;
-                               }
-                               else
+                               Type requestType = CastTo (_typeName, type);
+                               if (requestType == null)
                                        throw new RemotingException ("Cannot cast from client type '" + _typeName + "' to server type '" + type.FullName + "'");
+
+                               // Look for the method in the requested type. The method signature is provided
+                               // only if the method is overloaded in the requested type.
+                               _methodBase = RemotingServices.GetMethodBaseFromName (requestType, _methodName, _methodSignature);
+
+                               if (_methodBase == null)
+                                       throw new RemotingException ("Method " + _methodName + " not found in " + requestType);
+
+                               // If the method is implemented in an interface, look for the method implementation.
+                               // It can't be done in the previous GetMethodBaseFromName call because at that point we
+                               // may not yet have the method signature.
+                               if (requestType != type && requestType.IsInterface && !type.IsInterface) {
+                                       _methodBase = RemotingServices.GetVirtualMethod (type, _methodBase);
+                                       if (_methodBase == null)
+                                               throw new RemotingException ("Method " + _methodName + " not found in " + type);
+                               }
+
+                       } else {
+                               _methodBase = RemotingServices.GetMethodBaseFromMethodMessage (this);
+                               if (_methodBase == null) throw new RemotingException ("Method " + _methodName + " not found in " + TypeName);
+                       }
+
+
+#if NET_2_0
+                       if (_methodBase.IsGenericMethod && _methodBase.ContainsGenericParameters) {
+                               if (GenericArguments == null)
+                                       throw new RemotingException ("The remoting infrastructure does not support open generic methods.");
+                               _methodBase = ((MethodInfo) _methodBase).MakeGenericMethod (GenericArguments);
                        }
-                       _methodBase = RemotingServices.GetMethodBaseFromMethodMessage (this);
-                       if (_methodBase == null) throw new RemotingException ("Method " + _methodName + " not found in " + TypeName);
+#endif
                }
 
                Type CastTo (string clientType, Type serverType)
                {
-                       int i = clientType.IndexOf(',');
-                       if (i != -1) clientType = clientType.Substring (0,i).Trim();
-
+                       clientType = GetTypeNameFromAssemblyQualifiedName (clientType);
                        if (clientType == serverType.FullName) return serverType;
 
                        // base class hierarchy
 
                        Type baseType = serverType.BaseType;
                        while (baseType != null) {
-                       if (clientType == baseType.FullName) return baseType;
-                               baseType = baseType.BaseType;
-               }
+                               if (clientType == baseType.FullName) return baseType;
+                               baseType = baseType.BaseType;
+                       }
 
                        // Implemented interfaces
 
@@ -336,11 +373,23 @@ namespace System.Runtime.Remoting.Messaging {
                        foreach (Type itype in interfaces)
                                if (clientType == itype.FullName) return itype;
      
-               return null;
+                       return null;
+               }
+
+               static string GetTypeNameFromAssemblyQualifiedName (string aqname)
+               {
+#if NET_2_0
+                       int p = aqname.IndexOf ("]]");
+                       int i = aqname.IndexOf(',', p == -1 ? 0 : p + 2);
+#else
+                       int i = aqname.IndexOf(',');
+#endif
+                       if (i != -1) aqname = aqname.Substring (0, i).Trim ();
+                       return aqname;
                }
                
                [MonoTODO]
-               public void RootSetObjectData (SerializationInfo info, StreamingContext context)
+               public void RootSetObjectData (SerializationInfo info, StreamingContext ctx)
                {
                        throw new NotImplementedException ();
                }
@@ -351,6 +400,7 @@ namespace System.Runtime.Remoting.Messaging {
                        set { _targetIdentity = value; }
                }
 
+#if !NET_2_0
                public override string ToString ()
                {
                        string s = _typeName.Split(',')[0] + "." + _methodName + " (";
@@ -368,5 +418,17 @@ namespace System.Runtime.Remoting.Messaging {
                        s += ")";
                        return s;
                }
+#endif
+
+#if NET_2_0
+               Type[] GenericArguments {
+                       get {
+                               if (_genericArguments != null)
+                                       return _genericArguments;
+
+                               return _genericArguments = MethodBase.GetGenericArguments ();
+                       }
+               }
+#endif
        }
 }