- 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:
Suha Can
2010-04-05 19:22:38 -07:00
parent 5533fa1caf
commit 8f83475fe2
7 changed files with 155 additions and 6 deletions

View File

@@ -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;
}
}
}

View File

@@ -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; }
}
}

View File

@@ -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
}
}

View File

@@ -0,0 +1,7 @@
using System;
namespace Orchard.Commands {
[AttributeUsage(AttributeTargets.Property)]
public class OrchardSwitchAttribute : Attribute {
}
}

View 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; }
}
}
}

View File

@@ -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" />