jrich523 jrich523 - 3 months ago 25
ASP.NET (C#) Question

Command Pattern with url routing

So i've been looking to impliment a VERY simple command interface for a services so that http cmds can be sent to it to control it.

The part im struggling with is the best way to implement the commands, which will be based on the route. I've seen a lot on the command pattern which makes sense, but there is one thing im trying to modify. In all cases there is a dictionary which has the commands, is there some way to get rid of the dictionary and, for example, look at all static methods in a class? Im sure this can be done with reflection but i have yet to see an example of it, and when ever i look for the command pattern and reflection most people say to stay away from it.

My main goal is to make sure that if someone adds a command they don't forget to add it to the dictionary, I know i want all static methods to respond to routes.

Is this a good idea or should i say screw it and just stick to the normal pattern?

I should add im using the HttpListener with a very basic web server similar to this
Multi-threading with .Net HttpListener

and the best example i've seen of the command pattern for what im looking to do is this
using the command and factory design patterns for executing queued jobs

Full Solution

//simple interface
interface ICommand
{
bool Execute();
}

//example cmd
public class cmd_Restart:ICommand
{
public bool Execute()
{
//put your code here
//return true or false for success
logger.writeLog("It was called!");
return true;
}
}

class commands
{
private static Dictionary<string, Type> _commands;
public commands()
{
loadCommands();
}

public ICommand GetCommand(string cmdName)
{
//should probably be more complex to make sure its found
return (ICommand)Activator.CreateInstance(_commands[cmdName]);
}

private void loadCommands()
{
_commands = new Dictionary<string, Type>();
var cmdType = typeof(ICommand);

_commands = AppDomain.CurrentDomain.GetAssemblies()
.First(a => a.GetName().Name == "DomoticzServiceManagerTest")
.GetTypes()
.Where(t => t.Name.StartsWith("cmd_"))
.ToDictionary(c => c.Name.Substring(4).ToLower(),
c => c);
}
}

Answer

Third time lucky!

Here is some code which will find all types implementing a particular interface, such as your ICommand interface.

Register each type in a Dictionary<string, Type> - type name vs type, say.

When a request comes in, get the type. From the dictionary and do something like this;

var command = (ICommand)Activator.CreateInstance(commandType);
command.Execute();

So now you've got a system that finds types without having to register them, and automatic dispatch.

It's a bit basic but it's a pattern that has worked for me in the past.

Comments