I am working on a project that needs to be very extendable. It is about performing actions on the basis of a string code or an enum value. I am now using a switch-case statement and calling the methods manually.
What I would like to do is loop through the database records (and eventually get the enum value or string code), call the method "PerformAction" and make it possible to implement the classes or methods later.
public bool PerformAction(ActionToPerform actionToPerform)
{
bool isPerformed = false;
switch (actionToPerform.Action.Code)
{
case "MAIL":
isPerformed = Actions.SendEmail(actionToPerform);
break;
case "RESTART":
isPerformed = Actions.RestartSendport();
break;
case "EVENT-LOG":
isPerformed = Actions.AddToEventLog();
break;
}
//Do some more
return isPerformed;
}
I want to be able to implement the actions like SendEmail, RestartSendport and AddToEventLog later. I know this can somehow be done using reflection and giving the methods the name of the CODE (e.g. "MAIL.cs") so I can avoid using the switch case and perform one single call.
I need this to be very dynamic and in another library, so I was wondering if there is a best practice or a nice design pattern for this kind of problem.
-
Composition over inheritance is the way en.wikipedia.org/wiki/Composition_over_inheritance. Make it dependency injectedFendy– Fendy2013年05月16日 11:45:06 +00:00Commented May 16, 2013 at 11:45
-
I don't see how I could use this in my situation, would you be so kind, to give an example?Nick N.– Nick N.2013年05月16日 11:50:35 +00:00Commented May 16, 2013 at 11:50
2 Answers 2
You can start with creating a dictionary:
private Dictionary<ActionType, ActionBase> actions;
So instead of switch (currentActionType) you can do something like this:
if (actions.ContainsKey(currentActionType))
actions[currentActionType].Run(someArgs);
This way you separate actions mapping from actions invocation. The mapping can be done in constructor:
actions[ActionType.SendEmail] = new SendEmailAction();
actions[ActionType.OtherAction] = new OtherAction();
After this you can extract the actions dictionary to a separate ActionsRepository and inject it as a dependency. The repository can have a method RegisterAction(ActionType type, ActionBase action) for creating a mapping at runtime.
Comments
If you can manage to unify your action invocation pattern, you can add some ID field to your base Action class and invoke it this way:
public bool PerformAction(ActionToPerform actionToPerform)
{
bool isPerformed = false;
var foundAction = Actions.SingleOrDefault(a => a.Code == actionToPerform.Action.Code);
if (foundAction != null)
{
isPerformed = foundAction.Invoke();
}
//Do some more
return isPerformed;
}
Comments
Explore related questions
See similar questions with these tags.