Allow actions to invoke static methods

Fixes #177
This commit is contained in:
Antony Male 2021-02-16 08:43:04 +00:00
parent c82cdb9321
commit 6e2bc6e36c
3 changed files with 52 additions and 6 deletions

View File

@ -42,7 +42,7 @@ namespace Stylet.Xaml
protected readonly ActionUnavailableBehaviour ActionNonExistentBehaviour; protected readonly ActionUnavailableBehaviour ActionNonExistentBehaviour;
/// <summary> /// <summary>
/// Gets the object on which methods will be invokced /// Gets the object on which methods will be invoked
/// </summary> /// </summary>
public object Target public object Target
{ {
@ -128,10 +128,19 @@ namespace Stylet.Xaml
} }
else else
{ {
var newTargetType = newTarget.GetType(); BindingFlags bindingFlags;
if (newTarget is Type newTargetType)
{
bindingFlags = BindingFlags.Public | BindingFlags.Static;
}
else
{
newTargetType = newTarget.GetType();
bindingFlags = BindingFlags.Public | BindingFlags.Instance;
}
try try
{ {
targetMethodInfo = newTargetType.GetMethod(this.MethodName); targetMethodInfo = newTargetType.GetMethod(this.MethodName, bindingFlags);
if (targetMethodInfo == null) if (targetMethodInfo == null)
this.logger.Warn("Unable to find method {0} on {1}", this.MethodName, newTargetType.Name); this.logger.Warn("Unable to find method {0} on {1}", this.MethodName, newTargetType.Name);
@ -199,7 +208,8 @@ namespace Stylet.Xaml
try try
{ {
this.TargetMethodInfo.Invoke(this.Target, parameters); var target = this.TargetMethodInfo.IsStatic ? null : this.Target;
this.TargetMethodInfo.Invoke(target, parameters);
} }
catch (TargetInvocationException e) catch (TargetInvocationException e)
{ {

View File

@ -2,6 +2,7 @@
using Stylet; using Stylet;
using Stylet.Xaml; using Stylet.Xaml;
using System; using System;
using System.Runtime.CompilerServices;
using System.Windows; using System.Windows;
namespace StyletUnitTests namespace StyletUnitTests
@ -68,6 +69,12 @@ namespace StyletUnitTests
public void DoSomething() { } public void DoSomething() { }
} }
public class StaticTarget
{
public static bool DidSomething;
public static void DoSomething() => DidSomething = true;
}
private DependencyObject subject; private DependencyObject subject;
private Target target; private Target target;
@ -77,6 +84,7 @@ namespace StyletUnitTests
this.target = new Target(); this.target = new Target();
this.subject = new DependencyObject(); this.subject = new DependencyObject();
View.SetActionTarget(this.subject, this.target); View.SetActionTarget(this.subject, this.target);
StaticTarget.DidSomething = false;
} }
[Test] [Test]
@ -315,5 +323,16 @@ namespace StyletUnitTests
cmd.Execute(null); cmd.Execute(null);
Assert.IsTrue(this.target.DoSomethingCalled); Assert.IsTrue(this.target.DoSomethingCalled);
} }
[Test]
public void SupportsStaticTargets()
{
var cmd = new CommandAction(this.subject, null, "DoSomething", ActionUnavailableBehaviour.Throw, ActionUnavailableBehaviour.Throw);
View.SetActionTarget(this.subject, typeof(StaticTarget));
Assert.True(cmd.CanExecute(null));
cmd.Execute(null);
Assert.True(StaticTarget.DidSomething);
}
} }
} }

View File

@ -74,6 +74,12 @@ namespace StyletUnitTests
{ {
} }
public class StaticTarget
{
public static bool DidSomething;
public static void DoSomething() => DidSomething = true;
}
private DependencyObject subject; private DependencyObject subject;
private Target target; private Target target;
private EventInfo eventInfo; private EventInfo eventInfo;
@ -87,6 +93,7 @@ namespace StyletUnitTests
this.eventInfo = typeof(Subject).GetEvent("SimpleEventHandler"); this.eventInfo = typeof(Subject).GetEvent("SimpleEventHandler");
this.dependencyChangedEventInfo = typeof(Subject).GetEvent("DependencyChangedEventHandler"); this.dependencyChangedEventInfo = typeof(Subject).GetEvent("DependencyChangedEventHandler");
View.SetActionTarget(this.subject, this.target); View.SetActionTarget(this.subject, this.target);
StaticTarget.DidSomething = false;
} }
[Test] [Test]
@ -269,13 +276,23 @@ namespace StyletUnitTests
{ {
var view = new DependencyObject(); var view = new DependencyObject();
var backupView = new DependencyObject(); var backupView = new DependencyObject();
var cmd = new CommandAction(view, backupView, "DoSomething", ActionUnavailableBehaviour.Throw, ActionUnavailableBehaviour.Throw); var cmd = new EventAction(view, backupView, this.eventInfo.EventHandlerType, "DoSomething", ActionUnavailableBehaviour.Throw, ActionUnavailableBehaviour.Throw);
View.SetActionTarget(backupView, this.target); View.SetActionTarget(backupView, this.target);
view.SetValue(FrameworkElement.DataContextProperty, this.target); view.SetValue(FrameworkElement.DataContextProperty, this.target);
cmd.Execute(null); cmd.GetDelegate().DynamicInvoke(null, null);
Assert.IsTrue(this.target.DoSomethingCalled); Assert.IsTrue(this.target.DoSomethingCalled);
} }
[Test]
public void SupportsStaticTargets()
{
var cmd = new EventAction(this.subject, null, this.eventInfo.EventHandlerType, "DoSomething", ActionUnavailableBehaviour.Throw, ActionUnavailableBehaviour.Throw);
View.SetActionTarget(this.subject, typeof(StaticTarget));
cmd.GetDelegate().DynamicInvoke(null, null);
Assert.True(StaticTarget.DidSomething);
}
} }
} }