Fix bug #2927: lookup event bound methods from root instance, not current object.
authorAtsushi Eno <atsushieno@veritas-vos-liberabit.com>
Thu, 19 Jan 2012 09:30:33 +0000 (18:30 +0900)
committerAtsushi Eno <atsushi@ximian.com>
Thu, 19 Jan 2012 09:30:33 +0000 (18:30 +0900)
mcs/class/System.Xaml/System.Xaml/XamlObjectWriter.cs
mcs/class/System.Xaml/System.Xaml/XamlWriterInternalBase.cs
mcs/class/System.Xaml/Test/System.Xaml/TestedTypes.cs
mcs/class/System.Xaml/Test/System.Xaml/XamlObjectWriterTest.cs
mcs/class/System.Xaml/Test/XmlFiles/LookupCorrectEvent.xml [new file with mode: 0644]
mcs/class/System.Xaml/Test/XmlFiles/LookupCorrectEvent2.xml [new file with mode: 0644]
mcs/class/System.Xaml/Test/XmlFiles/LookupCorrectEvent3.xml [new file with mode: 0644]

index deed521407018815973368ddd8ea69ea939e9730..edcfeefbafa624c4826746ba5d9a6fd9bf9a7685 100644 (file)
@@ -241,6 +241,7 @@ namespace System.Xaml
                                        state.Value = obj;
                                        state.IsInstantiated = true;
                                }
+                               root_state = state;
                        }
                        object_states.Push (state);
                        if (!state.Type.IsContentValue (service_provider))
@@ -359,7 +360,7 @@ namespace System.Xaml
                                throw new XamlObjectWriterException (String.Format ("Event {0} has no underlying member to attach event", member));
 
                        int idx = value.LastIndexOf ('.');
-                       var xt = idx < 0 ? member.DeclaringType : ResolveTypeFromName (value.Substring (0, idx));
+                       var xt = idx < 0 ? root_state.Type : ResolveTypeFromName (value.Substring (0, idx));
                        if (xt == null)
                                throw new XamlObjectWriterException (String.Format ("Referenced type {0} in event {1} was not found", value, member));
                        if (xt.UnderlyingType == null)
@@ -369,11 +370,13 @@ namespace System.Xaml
                        // get an appropriate MethodInfo overload whose signature matches the event's handler type.
                        // FIXME: this may need more strict match. RuntimeBinder may be useful here.
                        var eventMethodParams = ev.EventHandlerType.GetMethod ("Invoke").GetParameters ();
-                       var mi = xt.UnderlyingType.GetMethod (mn, (from pi in eventMethodParams select pi.ParameterType).ToArray ());
+                       
+                       var target = root_state.Value;
+                       var mi = target.GetType().GetMethod (mn, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, (from pi in eventMethodParams select pi.ParameterType).ToArray (), null);
                        if (mi == null)
                                throw new XamlObjectWriterException (String.Format ("Referenced value method {0} in type {1} indicated by event {2} was not found", mn, value, member));
                        var obj = object_states.Peek ().Value;
-                       ev.AddEventHandler (obj, Delegate.CreateDelegate (ev.EventHandlerType, obj, mi));
+                       ev.AddEventHandler (obj, Delegate.CreateDelegate (ev.EventHandlerType, target, mi));
                }
 
                void SetValue (XamlMember member, object value)
index 31760ca12e3dc3d8e9c7d9486c457afa0c6d60f3..d22845feeef26f42324d2dc95d70fb6633478223 100644 (file)
@@ -55,6 +55,7 @@ namespace System.Xaml
 
                internal IValueSerializerContext service_provider;
 
+               internal ObjectState root_state;
                internal Stack<ObjectState> object_states = new Stack<ObjectState> ();
                internal PrefixLookup prefix_lookup {
                        get { return (PrefixLookup) service_provider.GetService (typeof (INamespacePrefixLookup)); }
index acf3711be4963bdeacda9fdbfa54d6c737af2199..88fcce250dd29a404f2e5085b8b0250f5205e53f 100755 (executable)
@@ -1081,4 +1081,87 @@ namespace SecondTest
        #endregion
 }
 
+#region "xamarin bug #2927"
+namespace XamarinBug2927
+{
+       public class RootClass
+       {
+               public RootClass ()
+               {
+                       Child = new MyChildClass ();
+               }
+               
+               public bool Invoked;
+               
+               public ChildClass Child { get; set; }
+       }
+
+       public class MyRootClass : RootClass
+       {
+               public void HandleMyEvent (object sender, EventArgs e)
+               {
+                       Invoked = true;
+               }
+       }
+
+       public class RootClass2
+       {
+               public RootClass2 ()
+               {
+                       Child = new MyChildClass ();
+               }
+               
+               public bool Invoked;
+               
+               public ChildClass Child { get; set; }
+               
+               public void HandleMyEvent (object sender, EventArgs e)
+               {
+                       Invoked = true;
+               }
+       }
+
+       public class MyRootClass2 : RootClass2
+       {
+       }
+
+       public class ChildClass
+       {
+               public bool Invoked;
+               
+               public DescendantClass Descendant { get; set; }
+       }
+
+       public class MyChildClass : ChildClass
+       {
+               public MyChildClass ()
+               {
+                       Descendant = new DescendantClass () { Value = "x" };
+               }
+       
+               public void HandleMyEvent (object sender, EventArgs e)
+               {
+                       Invoked = true;
+               }
+       }
+
+       public class DescendantClass
+       {
+               public bool Invoked;
+               public event EventHandler DoWork;
+               public string Value { get; set; }
+       
+               public void Work ()
+               {
+                       DoWork (this, EventArgs.Empty);
+               }
+       
+               public void HandleMyEvent (object sender, EventArgs e)
+               {
+                       Invoked = true;
+               }
+       }
+}
+#endregion
+
 
index 53e2e7b2313bf5d21a82500843560227e035f43c..6a89ff930d4efe4fb81e4b8671abb35e885db168 100755 (executable)
@@ -733,6 +733,29 @@ namespace MonoTests.System.Xaml
                        ow.Close ();
                        Assert.AreEqual (typeof (int), ow.Result, "#1");
                }
+
+               [Test]
+               public void LookupCorrectEventBoundMethod ()
+               {
+                       var o = (XamarinBug2927.MyRootClass) XamlServices.Load (GetReader ("LookupCorrectEvent.xml"));
+                       o.Child.Descendant.Work ();
+                       Assert.IsTrue (o.Invoked, "#1");
+                       Assert.IsFalse (o.Child.Invoked, "#2");
+                       Assert.IsFalse (o.Child.Descendant.Invoked, "#3");
+               }
+               
+               [Test]
+               [ExpectedException (typeof (XamlObjectWriterException))]
+               public void LookupCorrectEventBoundMethod2 ()
+               {
+                       XamlServices.Load (GetReader ("LookupCorrectEvent2.xml"));
+               }
+               
+               [Test]
+               public void LookupCorrectEventBoundMethod3 ()
+               {
+                       XamlServices.Load (GetReader ("LookupCorrectEvent3.xml"));
+               }
                
                // common use case based tests (to other readers/writers).
 
diff --git a/mcs/class/System.Xaml/Test/XmlFiles/LookupCorrectEvent.xml b/mcs/class/System.Xaml/Test/XmlFiles/LookupCorrectEvent.xml
new file mode 100644 (file)
index 0000000..bbf9a49
--- /dev/null
@@ -0,0 +1,9 @@
+<MyRootClass xmlns="clr-namespace:XamarinBug2927;assembly=System.Xaml_test_net_4_0" >
+  <MyRootClass.Child>
+    <MyChildClass>
+      <MyChildClass.Descendant>
+        <DescendantClass Value='x' DoWork='HandleMyEvent' />
+      </MyChildClass.Descendant>
+    </MyChildClass>
+  </MyRootClass.Child>
+</MyRootClass>
diff --git a/mcs/class/System.Xaml/Test/XmlFiles/LookupCorrectEvent2.xml b/mcs/class/System.Xaml/Test/XmlFiles/LookupCorrectEvent2.xml
new file mode 100644 (file)
index 0000000..ac154d3
--- /dev/null
@@ -0,0 +1,9 @@
+<RootClass xmlns="clr-namespace:XamarinBug2927;assembly=System.Xaml_test_net_4_0" >
+  <RootClass.Child>
+    <MyChildClass>
+      <MyChildClass.Descendant>
+        <DescendantClass Value='x' DoWork='HandleMyEvent' />
+      </MyChildClass.Descendant>
+    </MyChildClass>
+  </RootClass.Child>
+</RootClass>
diff --git a/mcs/class/System.Xaml/Test/XmlFiles/LookupCorrectEvent3.xml b/mcs/class/System.Xaml/Test/XmlFiles/LookupCorrectEvent3.xml
new file mode 100644 (file)
index 0000000..c062953
--- /dev/null
@@ -0,0 +1,9 @@
+<MyRootClass2 xmlns="clr-namespace:XamarinBug2927;assembly=System.Xaml_test_net_4_0" >
+  <MyRootClass2.Child>
+    <MyChildClass>
+      <MyChildClass.Descendant>
+        <DescendantClass Value='x' DoWork='HandleMyEvent' />
+      </MyChildClass.Descendant>
+    </MyChildClass>
+  </MyRootClass2.Child>
+</MyRootClass2>