如何将委托传递给泛型委托的函数?

时间:2019-01-23 21:04:16

标签: c# generics delegates

我有一个从各种Windows控件返回相关文本的功能。
我希望能够创造出一些更优雅,更不静态的东西。 这是我想要的功能代码:

    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";
    }

我想做的是这样的:

呼叫代码:

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

功能:

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

我猜我在做错误的一般性方面,但是我还没有找出正确的方法来做。 或者也许我完全在这里吃午饭。

2 个答案:

答案 0 :(得分:2)

这是原始代码的更清晰版本。它不使用任何反射,泛型或ToString调用。相反,它使用 pattern matching 开关语句:

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;
    }
}

顺便说一句,您将名称​​ controller 用于类型Control的变量会产生误导;控制器在其他情况下具有实际意义。

一种替代方法是创建一个Dictionary<Type, Func<Control, string>>,其中的条目看起来像{typeof(Textbox), c=>((TextBox)c).Text},但是我认为这比仅使用如上所示的开关要清楚得多。

另一件事:您可以将此功能设为Control类型的扩展方法(通过将其放在静态类中,然后将关键字{参数列表中this之前的{1}}。我可能会将其重命名为Control。那时,您只需为页面上的任何控件说GetTextValue。不幸的是,C#中还没有var textValue = anyControl.GetTextValue();

答案 1 :(得分:0)

使用反射非常容易。您要做的是使用类的类型来检索其属性。然后,您在对象上请求该属性的值,就得到了该值。

这里是一个简单的快速反思。其作用是获取对象的类型,请求名为SelectedValue的属性,然后查询combobox对象以获取值,最后将其转换为字符串。

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

在同一函数中添加了同样的内容,并且很通用,而且可能会发生错误处理

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

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

    return value;
}