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

View File

@ -2,6 +2,7 @@
using Stylet;
using Stylet.Xaml;
using System;
using System.Runtime.CompilerServices;
using System.Windows;
namespace StyletUnitTests
@ -68,6 +69,12 @@ namespace StyletUnitTests
public void DoSomething() { }
}
public class StaticTarget
{
public static bool DidSomething;
public static void DoSomething() => DidSomething = true;
}
private DependencyObject subject;
private Target target;
@ -77,6 +84,7 @@ namespace StyletUnitTests
this.target = new Target();
this.subject = new DependencyObject();
View.SetActionTarget(this.subject, this.target);
StaticTarget.DidSomething = false;
}
[Test]
@ -315,5 +323,16 @@ namespace StyletUnitTests
cmd.Execute(null);
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 Target target;
private EventInfo eventInfo;
@ -87,6 +93,7 @@ namespace StyletUnitTests
this.eventInfo = typeof(Subject).GetEvent("SimpleEventHandler");
this.dependencyChangedEventInfo = typeof(Subject).GetEvent("DependencyChangedEventHandler");
View.SetActionTarget(this.subject, this.target);
StaticTarget.DidSomething = false;
}
[Test]
@ -269,13 +276,23 @@ namespace StyletUnitTests
{
var view = 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.SetValue(FrameworkElement.DataContextProperty, this.target);
cmd.Execute(null);
cmd.GetDelegate().DynamicInvoke(null, null);
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);
}
}
}