Reputation: 1425
I'm trying to design a console application where the menus are generated from a data structure of some sort and each menu item can have a handler/action specified (which could just be displaying a different menu). Sorry if this is sounding convoluted already!
I'm having a lot of trouble figuring out the correct way to go about this. It's my first C# application and I feel like I've been reading about delegates for hours and I'm still not even sure if I'm supposed to be using them.
I have a lot of existing code but I feel like it might be better if I get some overall direction before trying to fix what's potentially broken at the foundations. I'll try to describe what I'm trying to do:
It's this "pointer to a handler" that I'm having trouble with. How should this handler be represented in the MenuItem object? How can I call the handler from the menu prompt? Am I going about it in a completely wrong way?
Hopefully this makes sense :)
Upvotes: 0
Views: 1220
Reputation: 8782
I think delegates might be good starting point. First, because they are fairly popular in C# and since you are started to learn C# it can be a good practice. Secondly, implementing your application using delegates should be fairly straightforward.
Let's consider Action<T>
and Func<T>
delegates. First one can perform some action but will not return any value. Second one returns some value of type T. Both types can take up to 16 parameters. Basically their main behavior is to be a placeholder for a method.
So let's take a look at some example, embedded in the context of your application:
public class MenuItem<T>
{
public string Description { get; set; }
public char HotKey { get; set; }
public Func<T> FirstHandler { get; set; } // returns some value
public Action<T> SecondHandler { get; set; } // does not return any value
// let's use this method to invoke the first handler
public T DoSomething()
{
// this handler is of type Func<T> so it will return a value of type T
return this.FirstHandler.Invoke();
}
// let's use this method to invoke the second handler
public void DoSomethingElse(T input)
{
this.SecondHandler.Invoke(input);
}
}
In case of Func
if it has more than one argument than the last one is return type. Others are input types. So for instance Func<int, char, string>
will accept a method that takes int
and char
as an input but returns string
. You get some help from Visual Studio - in the delegate description it displays in
and out
words in front of the parameters to signal whether it's input or output parameter.
Now, having the MenuItem
class created you can use it in the following way:
class Program
{
// A method that takes no input arguments but returns string
private static string ReturnHelloWorld()
{
return "Hello World";
}
static void Main(string[] args)
{
MenuItem<string> menuItem = new MenuItem<string>();
// FirstHandler signature is Func<T>
// So it doesn't take any input arguments
// and returns T - in our case string
menuItem.FirstHandler = ReturnHelloWorld;
// SecondHandler signature is Action<T>
// So it takes one input argument of type T (here, string)
// and returns void
menuItem.SecondHandler = Console.WriteLine;
// Now use a method of MenuItem class to invoke FirstHandler.
string menuItemMessage = menuItem.DoSomething();
// Use another method to invoke SecondHandler.
menuItem.DoSomethingElse(menuItemMessage);
}
}
Note that it's only a very elementary starting point for your problem. But it allows you to create menu items and assign different behaviours to the items.
Upvotes: 1