In my application I have the need to reference various types of Action
Action action1;
Action<int> action2;
Action actRef = action2; // Error: actRef is not the same type as action2
Basically I would like a type with which I can reference both action1 and action2. Is this possible?
The best solution I can think of is to wrap the Action<...> in another class that implements some interface.
public interface MyInterfaceType
{
}
public class MyActionWrapper : MyInterfaceType
{
public Action MyAction { get; set; }
}
public class MyActionWrapper<T> : MyInterfaceType
{
public Action<T> MyAction { get; set; }
}
Then carry around references to MyInterfaceType.
public class MyActionsHolder
{
List<MyInterfaceType> MyActions { get; set; }
public void DoActions()
{
foreach(MyInterfaceType anAction in MyActions)
{
if(anAction is MyActionWrapper)
((MyActionWrapper)anAction).MyAction();
else if(anAction is MyActionWrapper<int>)
((MyActionWrapper<int>)anAction).MyAction(1);
}
}
}
Is there a better solution? Or a way to clean this solution up?
More background on the specifics. I have written a simple scripting language which I am trying to parse into Action, each Action represents a parsed command from the script. As one commentor pointed out I can easily just wrap an Action with another
Action myParameterlessAction = new Action(() => MySingleParmAction(1));
though for a few of my commands I allow the user to supply a psuedo argument/variable. For example I might have an argument FOO that allows one argument. The argument is either a value for FOO or it is a "variable" meaning the current value of FOO when the command is executed.
FOO 231 // Set FOO = 231
FOO VAL_FOO // Set FOO to the desired value of FOO, whatever it may be at this time
So when I go to parse this second type of command I create an Action that takes a parameter so I can supply it when the time comes.
Action fooCommand1 = new Action(delegate() { MyForm.SetFooValue(231); });
Action<int> fooCommand2 = MyForm.SetFooValue;
I would like to be able to collect all Action create from parsing into a List<...> that I can then loop over and execute each action.. (I do realize that I will need a method to determine which Action need parameters supplied and how to determine what to supply them with; based on my solution above this information would be in MyInterfaceType most likely).
EDIT: In response to @The Anathema's answer, I have a command in my language that allows a user to wait for some period of time before continuing. The parsing of the script to the Action would look like this
public KeyValuePair<Delegate, object[]> CommandAction { get; set; }
...
Action commandDelegate = new Action(async delegate()
{
await Task.Delay(msWait);
});
result.CommandAction = new KeyValuePair<Delegate, object[]>(commandDelegate, null);
Will Action.DynamicInvoke block until the Task.Delay(...) has completed? Where will the invocation happen, on the current thread or the thread on which the Action was created? Can I change either of these options?
Also per this SO answer I take it it would be worthwhile to try to resolve the Actions that are parameterless to Action myAct so that I can Invoke them instead of DynamicInvoke (Seeing that DynamicInvoke takes orders of magnitude longer to execute per the linked answer)?