mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
- Command Handler support for switches.
- OrchardSwitch attribute for bool, int, string properties. - OrchardSwitches attribute for commands to specify which switches they support. - Unit tests. --HG-- branch : dev
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using NUnit.Framework;
|
||||
using System.Collections.Specialized;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Commands;
|
||||
using System;
|
||||
|
||||
@@ -27,20 +28,86 @@ namespace Orchard.Tests.Commands {
|
||||
|
||||
[Test]
|
||||
public void TestCommandWithCustomAlias() {
|
||||
CommandContext commandContext = new CommandContext { Command = "bar" };
|
||||
CommandContext commandContext = new CommandContext { Command = "Bar" };
|
||||
_handler.Execute(commandContext);
|
||||
Assert.That(commandContext.Output, Is.EqualTo("Hello World!"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBooleanSwitchForCommand() {
|
||||
CommandContext commandContext = new CommandContext { Command = "Baz", Switches = new NameValueCollection() };
|
||||
commandContext.Switches.Add("Verbose", "true");
|
||||
_handler.Execute(commandContext);
|
||||
Assert.That(commandContext.Output, Is.EqualTo("Command Baz Called : This was a test"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestIntSwitchForCommand() {
|
||||
CommandContext commandContext = new CommandContext { Command = "Baz", Switches = new NameValueCollection() };
|
||||
commandContext.Switches.Add("Level", "2");
|
||||
_handler.Execute(commandContext);
|
||||
Assert.That(commandContext.Output, Is.EqualTo("Command Baz Called : Entering Level 2"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestStringSwitchForCommand() {
|
||||
CommandContext commandContext = new CommandContext { Command = "Baz", Switches = new NameValueCollection() };
|
||||
commandContext.Switches.Add("User", "OrchardUser");
|
||||
_handler.Execute(commandContext);
|
||||
Assert.That(commandContext.Output, Is.EqualTo("Command Baz Called : current user is OrchardUser"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSwitchForCommandWithoutSupportForIt() {
|
||||
CommandContext commandContext = new CommandContext { Command = "Foo", Switches = new NameValueCollection() };
|
||||
commandContext.Switches.Add("User", "OrchardUser");
|
||||
Assert.Throws<InvalidOperationException>(() => _handler.Execute(commandContext));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNotExistingSwitch() {
|
||||
CommandContext commandContext = new CommandContext { Command = "Foo", Switches = new NameValueCollection() };
|
||||
commandContext.Switches.Add("ThisSwitchDoesNotExist", "Insignificant");
|
||||
Assert.Throws<InvalidOperationException>(() => _handler.Execute(commandContext));
|
||||
}
|
||||
}
|
||||
|
||||
public class StubCommandHandler : DefaultOrchardCommandHandler {
|
||||
[OrchardSwitch]
|
||||
public bool Verbose { get; set; }
|
||||
|
||||
[OrchardSwitch]
|
||||
public int Level { get; set; }
|
||||
|
||||
[OrchardSwitch]
|
||||
public string User { get; set; }
|
||||
|
||||
public string Foo() {
|
||||
return "Command Foo Executed";
|
||||
}
|
||||
|
||||
[OrchardCommand("bar")]
|
||||
[OrchardCommand("Bar")]
|
||||
public string Hello() {
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
[OrchardSwitches("Verbose, Level, User")]
|
||||
public string Baz() {
|
||||
string trace = "Command Baz Called";
|
||||
|
||||
if (Verbose) {
|
||||
trace += " : This was a test";
|
||||
}
|
||||
|
||||
if (Level == 2) {
|
||||
trace += " : Entering Level 2";
|
||||
}
|
||||
|
||||
if (!String.IsNullOrEmpty(User)) {
|
||||
trace += " : current user is " + User;
|
||||
}
|
||||
|
||||
return trace;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,10 @@
|
||||
namespace Orchard.Commands {
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace Orchard.Commands {
|
||||
public class CommandContext {
|
||||
public string Input { get; set; }
|
||||
public string Output { get; set; }
|
||||
public string Command { get; set; }
|
||||
public string[] Arguments { get; set; }
|
||||
public NameValueCollection Switches { get; set; }
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Reflection;
|
||||
using Orchard.Localization;
|
||||
|
||||
@@ -13,14 +15,46 @@ namespace Orchard.Commands {
|
||||
#region Implementation of ICommandHandler
|
||||
|
||||
public void Execute(CommandContext context) {
|
||||
if (context.Switches != null && context.Switches.Count > 0) {
|
||||
foreach (var commandSwitch in context.Switches.AllKeys) {
|
||||
PropertyInfo propertyInfo = GetType().GetProperty(commandSwitch);
|
||||
if (propertyInfo == null) {
|
||||
throw new InvalidOperationException(T("Switch : ") + commandSwitch + T(" was not found"));
|
||||
}
|
||||
if (propertyInfo.GetCustomAttributes(typeof(OrchardSwitchAttribute), false).Length == 0) {
|
||||
throw new InvalidOperationException(T("A property of the name ") + commandSwitch + T(" exists but is not decorated with the OrchardSwitch attribute"));
|
||||
}
|
||||
string stringValue = context.Switches[commandSwitch];
|
||||
if (propertyInfo.PropertyType.IsAssignableFrom(typeof(bool))) {
|
||||
bool boolValue;
|
||||
Boolean.TryParse(stringValue, out boolValue);
|
||||
propertyInfo.SetValue(this, boolValue, null);
|
||||
}
|
||||
else if (propertyInfo.PropertyType.IsAssignableFrom(typeof(int))) {
|
||||
int intValue;
|
||||
Int32.TryParse(stringValue, out intValue);
|
||||
propertyInfo.SetValue(this, intValue, null);
|
||||
}
|
||||
else if (propertyInfo.PropertyType.IsAssignableFrom(typeof(string))) {
|
||||
propertyInfo.SetValue(this, stringValue, null);
|
||||
}
|
||||
else {
|
||||
throw new InvalidOperationException(T("No property named ") + commandSwitch +
|
||||
T(" found of type bool, int or string"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (MethodInfo methodInfo in GetType().GetMethods()) {
|
||||
if (String.Equals(methodInfo.Name, context.Command, StringComparison.OrdinalIgnoreCase)) {
|
||||
CheckMethodForSwitches(methodInfo, context.Switches);
|
||||
context.Output = (string)methodInfo.Invoke(this, null);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (OrchardCommandAttribute commandAttribute in methodInfo.GetCustomAttributes(typeof(OrchardCommandAttribute), false)) {
|
||||
if (String.Equals(commandAttribute.Command, context.Command, StringComparison.OrdinalIgnoreCase)) {
|
||||
CheckMethodForSwitches(methodInfo, context.Switches);
|
||||
context.Output = (string)methodInfo.Invoke(this, null);
|
||||
return;
|
||||
}
|
||||
@@ -30,6 +64,21 @@ namespace Orchard.Commands {
|
||||
throw new InvalidOperationException(T("Command : ") + context.Command + T(" was not found"));
|
||||
}
|
||||
|
||||
private void CheckMethodForSwitches(MethodInfo methodInfo, NameValueCollection switches) {
|
||||
if (switches == null || switches.AllKeys.Length == 0)
|
||||
return;
|
||||
List<string> supportedSwitches = new List<string>();
|
||||
foreach (OrchardSwitchesAttribute switchesAttribute in methodInfo.GetCustomAttributes(typeof(OrchardSwitchesAttribute), false)) {
|
||||
supportedSwitches.AddRange(switchesAttribute.SwitchName);
|
||||
}
|
||||
foreach (var commandSwitch in switches.AllKeys) {
|
||||
if (!supportedSwitches.Contains(commandSwitch)) {
|
||||
throw new InvalidOperationException(T("Method ") + methodInfo.Name +
|
||||
T(" does not support switch ") + commandSwitch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
7
src/Orchard/Commands/OrchardSwitchAttribute.cs
Normal file
7
src/Orchard/Commands/OrchardSwitchAttribute.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
using System;
|
||||
|
||||
namespace Orchard.Commands {
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class OrchardSwitchAttribute : Attribute {
|
||||
}
|
||||
}
|
22
src/Orchard/Commands/OrchardSwitchesAttribute.cs
Normal file
22
src/Orchard/Commands/OrchardSwitchesAttribute.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Commands {
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class OrchardSwitchesAttribute : Attribute {
|
||||
private readonly IEnumerable<string> _switches;
|
||||
|
||||
public OrchardSwitchesAttribute(string switches) {
|
||||
List<string> switchList = new List<string>();
|
||||
foreach (var s in switches.Split(',')) {
|
||||
switchList.Add(s.Trim());
|
||||
}
|
||||
_switches = switchList;
|
||||
}
|
||||
|
||||
public IEnumerable<string> SwitchName {
|
||||
get { return _switches; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -129,10 +129,12 @@
|
||||
<Compile Include="Validation\Argument.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Commands\CommandAttribute.cs" />
|
||||
<Compile Include="Commands\OrchardCommandAttribute.cs" />
|
||||
<Compile Include="Commands\CommandContext.cs" />
|
||||
<Compile Include="Commands\DefaultOrchardCommandHandler.cs" />
|
||||
<Compile Include="Commands\ICommandHandler.cs" />
|
||||
<Compile Include="Commands\OrchardSwitchAttribute.cs" />
|
||||
<Compile Include="Commands\OrchardSwitchesAttribute.cs" />
|
||||
<Compile Include="ContentManagement\Aspects\ICommonAspect.cs" />
|
||||
<Compile Include="ContentManagement\Drivers\IContentItemDriver.cs" />
|
||||
<Compile Include="ContentManagement\Extenstions\UrlHelperExtensions.cs" />
|
||||
|
Reference in New Issue
Block a user