Nathan
Nathan

Reputation: 1425

Need help understanding dynamic menus in my C# console application

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

Answers (1)

PiotrWolkowski
PiotrWolkowski

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

Related Questions