Xamarin-5278: Fix Binder.SelectMethod when passed argument is COM object
authorEberhard Beilharz <eb1@sil.org>
Wed, 23 May 2012 13:21:49 +0000 (15:21 +0200)
committerEberhard Beilharz <eb1@sil.org>
Fri, 25 May 2012 09:59:38 +0000 (11:59 +0200)
This patch fixes the problem that reflection doesn't find the
constructor of a class if one of the arguments is a COM object
implemented in unmanaged code. In that case the proxy can't
be converted to a managed object and we didn't check if the
COM object implements the desired interface.

Change-Id: Ie086bbb898ae2de8bd38b9f81422086e017a859e

mcs/class/corlib/System.Reflection/Binder.cs

index 4f5a043fd281397d16dd723a63e9c078de8f863b..b04dfd8a536e89a4c6a5af6eefe5d706fa16aeca 100644 (file)
@@ -195,12 +195,12 @@ namespace System.Reflection
                                                if (i < names.Length)
                                                        continue;
 
-                                               selected = SelectMethod (bindingAttr, new MethodBase [] { m }, newTypes, newModifiers, true);
+                                               selected = SelectMethod (bindingAttr, new MethodBase [] { m }, newTypes, newModifiers, true, args);
                                                if (selected != null)
                                                        break;
                                        }
                                } else {
-                                       selected = SelectMethod (bindingAttr, match, types, modifiers, true);
+                                       selected = SelectMethod (bindingAttr, match, types, modifiers, true, args);
                                }
 
                                state = null;
@@ -451,10 +451,10 @@ namespace System.Reflection
                        public override MethodBase SelectMethod (BindingFlags bindingAttr, MethodBase [] match, Type [] types, ParameterModifier [] modifiers)
                        {
                                return SelectMethod (bindingAttr, match, types, modifiers,
-                                       false);
+                                       false, null);
                        }
 
-                       MethodBase SelectMethod (BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers, bool allowByRefMatch)
+                       MethodBase SelectMethod (BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers, bool allowByRefMatch, object[] parameters)
                        {
                                MethodBase m;
                                int i, j;
@@ -527,7 +527,34 @@ namespace System.Reflection
                                                result = m;
                                }
 
-                               return result;
+                               if (result != null || parameters == null)
+                                       return result;
+
+                               // Xamarin-5278: try with parameters that are COM objects
+                               for (i = 0; i < match.Length; ++i) {
+                                       m = match [i];
+                                       ParameterInfo[] args = m.GetParameters ();
+                                       if (args.Length != types.Length || args.Length != parameters.Length)
+                                               continue;
+                                       for (j = 0; j < types.Length; ++j) {
+                                               var requiredType = args [j].ParameterType;
+                                               if (types [j] == requiredType)
+                                                       continue;
+                                               if (types [j] == typeof (__ComObject) && requiredType.IsInterface) {
+                                                       var iface = Marshal.GetComInterfaceForObject (parameters [j], requiredType);
+                                                       if (iface != IntPtr.Zero) {
+                                                               // the COM object implements the desired interface
+                                                               Marshal.Release (iface);
+                                                               continue;
+                                                       }
+                                               }
+                                               break;
+                                       }
+
+                                       if (j == types.Length)
+                                               return m;
+                               }
+                               return null;
                        }
 
                        MethodBase GetBetterMethod (MethodBase m1, MethodBase m2, Type [] types)