简体   繁体   English

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

[英]How can I pass delegates to a function for generic delegates?

I have a function to return relevant text from various windows controls. 我有一个从各种Windows控件返回相关文本的功能。
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. 也许我完全在这里吃午饭。

Here's a cleaner (and clearer) version of your original code. 这是原始代码的更清晰的版本。 It doesn't use any reflection, generics or ToString calls. 它不使用任何反射,泛型或ToString调用。 Instead, it uses a pattern matching switch statement: 相反,它使用模式匹配 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;
    }
}

By the way, your use of the name controller for a variable of type Control is misleading; 顺便说一句,您将名称controller用于Control类型的变量会产生误导; 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. 一种替代方法是创建一个Dictionary<Type, Func<Control, string>> ,其中一个条目看起来像{typeof(Textbox), c=>((TextBox)c).Text} ,但是我认为那是一个比仅使用如我所示的开关要清晰得多。

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). 另一件事:您可以将此函数作为Control类型的扩展方法 (通过将其放在静态类中,并将关键字this置于Control之前的参数列表中)。 I'd probably rename it GetTextValue . 我可能会将其重命名为GetTextValue At that point, you could just say var textValue = anyControl.GetTextValue(); 那时,您可以说var textValue = anyControl.GetTextValue(); for any control on your page. 用于页面上的任何控件。 Unfortunately, there isn't an extension property yet in C# 不幸的是,C#中没有extension property

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. 它要做的是获取对象的类型,请求名为SelectedValue的属性,然后查询combobox对象以检索值,最后转换为字符串。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM