From: Akihiko Odaki Date: Fri, 3 May 2019 18:25:03 +0000 (+0900) Subject: [Xaml[C]] Allow to connect to static event handler (#5119) X-Git-Tag: accepted/tizen/5.5/unified/20200421.150457~405 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=92ee64e2f6863621e40a46ea83009342c47244f2;p=platform%2Fcore%2Fcsapi%2Fxsf.git [Xaml[C]] Allow to connect to static event handler (#5119) --- diff --git a/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs b/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs index 59a4736..2e7338a 100644 --- a/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs +++ b/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs @@ -937,14 +937,6 @@ namespace Xamarin.Forms.Build.Tasks var value = ((ValueNode)valueNode).Value; yield return Create(Ldloc, parent); - if (context.Root is VariableDefinition) - foreach (var instruction in (context.Root as VariableDefinition).LoadAs(adder.Parameters[0].ParameterType.ResolveGenericParameters(adder), module)) - yield return instruction; - else if (context.Root is FieldDefinition) { - yield return Create(Ldarg_0); - yield return Create(Ldfld, context.Root as FieldDefinition); - } else - throw new InvalidProgramException(); var declaringType = context.Body.Method.DeclaringType; while (declaringType.IsNested) declaringType = declaringType.DeclaringType; @@ -965,15 +957,29 @@ namespace Xamarin.Forms.Build.Tasks throw new XamlParseException($"Signature (parameter {i}) of EventHandler \"{context.Body.Method.DeclaringType.FullName}.{value}\" doesn't match the event type", iXmlLineInfo); //TODO check generic parameters if any + //FIXME: eventually get the right ctor instead fo the First() one, just in case another one could exists (not even sure it's possible). + var ctor = module.ImportReference(eventinfo.EventType.ResolveCached().GetConstructors().First()); + ctor = ctor.ResolveGenericParameters(eventinfo.EventType, module); + + if (handler.IsStatic) { + yield return Create(Ldnull); + } else { + if (context.Root is VariableDefinition) + foreach (var instruction in (context.Root as VariableDefinition).LoadAs(ctor.Parameters[0].ParameterType.ResolveGenericParameters(ctor), module)) + yield return instruction; + else if (context.Root is FieldDefinition) { + yield return Create(Ldarg_0); + yield return Create(Ldfld, context.Root as FieldDefinition); + } else + throw new InvalidProgramException(); + } + if (handler.IsVirtual) { yield return Create(Ldarg_0); yield return Create(Ldvirtftn, handler); } else yield return Create(Ldftn, handler); - //FIXME: eventually get the right ctor instead fo the First() one, just in case another one could exists (not even sure it's possible). - var ctor = module.ImportReference(eventinfo.EventType.ResolveCached().GetConstructors().First()); - ctor = ctor.ResolveGenericParameters(eventinfo.EventType, module); yield return Create(Newobj, module.ImportReference(ctor)); //Check if the handler has the same signature as the ctor (it should) yield return Create(Callvirt, module.ImportReference(adder)); diff --git a/Xamarin.Forms.Xaml.UnitTests/EventsConnection.xaml b/Xamarin.Forms.Xaml.UnitTests/EventsConnection.xaml index 7e48e1b..6fcba95 100644 --- a/Xamarin.Forms.Xaml.UnitTests/EventsConnection.xaml +++ b/Xamarin.Forms.Xaml.UnitTests/EventsConnection.xaml @@ -14,5 +14,7 @@ Clicked="HandleClickedPrivateAsync" /> + \ No newline at end of file diff --git a/Xamarin.Forms.Xaml.UnitTests/EventsConnection.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/EventsConnection.xaml.cs index e32788a..228923e 100644 --- a/Xamarin.Forms.Xaml.UnitTests/EventsConnection.xaml.cs +++ b/Xamarin.Forms.Xaml.UnitTests/EventsConnection.xaml.cs @@ -77,6 +77,16 @@ namespace Xamarin.Forms.Xaml.UnitTests baseForVirtualClicked++; } + protected static int staticClicked; + + // This is necessary because the interpreter searches the class + // specified by x:Class for a static method. + // See: https://github.com/xamarin/Xamarin.Forms/issues/5100 + static void HandleStaticClicked(object sender, EventArgs e) + { + staticClicked++; + } + [TestFixture] public class Tests { @@ -131,6 +141,23 @@ namespace Xamarin.Forms.Xaml.UnitTests Assert.AreEqual(0, layout.baseForVirtualClicked); Assert.AreEqual(1, layout.overrideClicked); } + + [TestCase(false)] + [TestCase(true)] + public void TestStaticHandler(bool useCompiledXaml) + { + try + { + var layout = new SubForEvents(useCompiledXaml); + Assert.AreEqual(0, staticClicked); + layout.elementWithStaticHandler.SendClicked(); + Assert.AreEqual(1, staticClicked); + } + finally + { + staticClicked = 0; + } + } } } @@ -151,5 +178,13 @@ namespace Xamarin.Forms.Xaml.UnitTests #pragma warning restore 1998 { } + + // This is necessary because the interpreter searches the subclass + // for a static method. + // See: https://github.com/xamarin/Xamarin.Forms/issues/5100 + static void HandleStaticClicked(object sender, EventArgs e) + { + staticClicked++; + } } } \ No newline at end of file diff --git a/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs b/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs index ca4d945..fa0a84f 100644 --- a/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs +++ b/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs @@ -413,7 +413,7 @@ namespace Xamarin.Forms.Xaml } try { - eventInfo.AddEventHandler(element, methodInfo.CreateDelegate(eventInfo.EventHandlerType, rootElement)); + eventInfo.AddEventHandler(element, methodInfo.CreateDelegate(eventInfo.EventHandlerType, methodInfo.IsStatic ? null : rootElement)); return true; } catch (ArgumentException ae) { exception = new XamlParseException($"Method {stringValue} does not have the correct signature", lineInfo, ae);