【问题标题】:How can I pass delegates to a function for generic delegates?如何将委托传递给通用委托的函数?
【发布时间】:2019-01-23 21:04:16
【问题描述】:

我有一个函数可以从各种窗口控件返回相关文本。
我希望能够创造一些更优雅、更少静态的东西。 这是我想要的功能的代码:

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

我猜我在一般方面做错了,但我一直无法找出正确的方法来做这件事。 或者也许我完全出去吃午饭了。

【问题讨论】:

  • 您的返回值是否始终是控件的属性并始终返回字符串?如果是的话,你看过反射吗?
  • 对于这个特定的函数,是的,返回类型将始终是字符串。我没有看反射,但我会检查文档。您认为有什么特别的地方可以在这​​里使用吗?
  • 好的,您的代码看起来不错,那么,您的问题是什么?你有什么问题?
  • @VadimMartynov 我遇到了一个错误,指出我无法将 ComboBoxValue 转换为 System.Func 。我认为这意味着我做了一些不太干净的事情。
  • 严格来说,您有一个对象应该公开一个名为Text 的属性,该属性返回一个string。这对我来说听起来像是一个界面。解决此问题的一种方法是创建这样的接口(例如IControlWithText),然后创建自己的派生TextBoxComboBox 类来实现它,然后使用它们来代替并使用接口类型传递它们。这显然可能是矫枉过正,这取决于你在做什么。

标签: c# generics delegates


【解决方案1】:

这是原始代码的更简洁(更清晰)的版本。它不使用任何反射、泛型或 ToString 调用。相反,它使用 模式匹配 switch 语句:

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

顺便说一句,您对Control 类型的变量使用名称​​controller 具有误导性;控制器在其他上下文中具有实际意义。

另一种方法是创建一个Dictionary&lt;Type, Func&lt;Control, string&gt;&gt;,其中一个条目看起来像{typeof(Textbox), c=&gt;((TextBox)c).Text},但我认为这比仅使用我展示的开关要清晰得多。

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

【讨论】:

  • 是的,我明白你关于清晰度问题的意思。我在想这将是一种简单的方法来传递可以在某些字段上执行的通用函数(我正在做一些自定义验证的东西),但看起来这不是一件简单的事情。不过,看起来您的方法适用于我需要做的事情。谢谢。
  • @Rolan:作为一个在一天之内审查方式太多代码的人,不要低估清晰的价值!
【解决方案2】:

使用反射非常简单。您所做的是使用类的类型来检索它们的属性。然后,您请求对象上该属性的值并获得该值。

这里是一个快速简单的反思。它所做的是获取对象的类型,请求名为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;
}

【讨论】:

    猜你喜欢
    • 2018-05-07
    • 2018-02-18
    • 2016-09-03
    • 1970-01-01
    • 1970-01-01
    • 2012-07-12
    • 1970-01-01
    • 1970-01-01
    • 2012-03-19
    相关资源
    最近更新 更多