Rolan
Rolan

Reputation: 3004

How can I pass delegates to a function for generic delegates?

I have a function to return relevant text from various windows controls.
I was hoping to be able to create something a little more elegant, and less static. Here's code that functions the way I want it to:

    public string returnText(Control controller)
    {
        string bob = controller.GetType().Name.ToString();
        if (bob == "TextBox")
            return ((TextBox)controller).Text;
        else if (bob == "ComboBox")
            return ((ComboBox)controller).SelectedValue.ToString();
        else
            return "Invalid Object";
    }

What I'd like to do is something like this:

Calling code:

        TextBoxValue del = x => x.Text;
        ComboBoxValue com = x => x.SelectedValue.ToString();
        bob.returnText2(this.cboUnitType, com);
        bob.returnText2(this.txtCurbAdj, del);

Function:

    public string returnText2<T>(T controller, Func<T, string> lambda )
    {
        return lambda(controller);
    }

I'm guessing I'm doing the generic side of things wrong, but I haven't been able to figure out the right way to do it. Or maybe I'm completely out to lunch here.

Upvotes: 0

Views: 61

Answers (2)

Flydog57
Flydog57

Reputation: 7111

Here's a cleaner (and clearer) version of your original code. It doesn't use any reflection, generics or ToString calls. Instead, it uses a pattern matching switch statement:

public static string ReturnText(Control control)
{
    switch (control)
    {
        case TextBox tb:
            return tb.Text;
        case ComboBox cb:
            return cb.SelectedText;
        //etc.
        default: return string.Empty;
    }
}

By the way, your use of the name controller for a variable of type Control is misleading; controller has real meaning in other contexts.

An alternative would be to create a Dictionary<Type, Func<Control, string>> where an entry would look like {typeof(Textbox), c=>((TextBox)c).Text}, but I think that would be a lot less clear than just using a switch like I've shown.

One other thing: You could make this function an extension method on the Control type (by putting it in a static class and putting the keyword this before Control in the parameter list). I'd probably rename it GetTextValue. At that point, you could just say var textValue = anyControl.GetTextValue(); for any control on your page. Unfortunately, there isn't an extension property yet in C#

Upvotes: 2

Franck
Franck

Reputation: 4440

Using reflection is pretty easy. What you do is use the type of the class to retrieve their properties. Then you request the value of that property on an object and you got the value.

here a quick simple reflection. What it does is get the type of the object, request the property named SelectedValue then query the combobox object to retrieve the value and finally convert as string.

var combobox = this.cboUnitType;
var value = combobox.GetType().GetProperty("SelectedValue").GetValue(combobox ).ToString();

Here the same thing made into a function and quite generic plus has possible error handling

private string GetValue(object obj, string property)
{
    var value = "";

    try
    {
        value = obj.GetType().GetProperty(property).GetValue(obj).ToString();
    }
    catch { }

    return value;
}

Upvotes: 0

Related Questions