为什么ListBox.DisplayMember接受字符串值?

时间:2019-03-22 19:02:44

标签: c# properties

我目前对C#还是很陌生,我的大部分知识都来自Java和Python。话虽如此,我目前有以下代码:

public class Person
{
    public int Person_ID { get; set; }
    public String First_Name { get; set; }
    public String Last_Name { get; set; }
    public String EmailAddress { get; set; }


    public String FullInfo
    {
        get
        {
            // Matthew Arnold (mtthwrnld@gmail.com)
            return $"{First_Name}, {Last_Name}, ({EmailAddress})";
        }
    }

}

此处使用“ FullInfo”属性:

private void button1_Click(object sender, EventArgs e)
{
    //'Results' is a ListBox
    //'people' is a List of type Person

    DataAccess db = new DataAccess();
    people = db.getPeople(lastNameText.Text);

    Results.DataSource = people;
    Results.DisplayMember = "FullInfo";
}

我的问题明确地涉及以下这一行:Results.DisplayMember = "FullInfo";

此分配实际上 如何工作?我们将DisplayMember设置为FullInfo属性,但是将其包装在String中。为什么我们不简单地做Results.DisplayMember = Person.FullInfo

编译器如何知道这不是旧的String?以这种方式访问​​该物业有什么好处?

3 个答案:

答案 0 :(得分:2)

您正在处理反射。看一下这个功能:

public static void GetDisplayName(object anyType, string displayName)
{
    var type = anyType.GetType();

    var displayProperty = type.GetProperty(displayName);
    if (displayProperty != null)
    {
        Console.WriteLine($"DisplayName is {displayProperty.GetValue(anyType)}");
        return;
    }

    var displayFiled = type.GetField(displayName);
    if (displayFiled != null)
    {
        Console.WriteLine($"DisplayName is {displayFiled.GetValue(anyType)}");
        return;
    }

    // can't find displayName
    Console.WriteLine($"DisplayName is {type.Name}");
}

如果您喜欢这样称呼

var person = new Person
{
    Person_ID = 42,
    First_Name = "First",
    Last_Name = "Last",
    EmailAddress = "name@domain.com"
};

GetDisplayName(person, "FullInfo");

它将打印

  

DisplayName是第一个,最后一个(name@domain.com)

就像您在问题示例中一样,我们仅将"FullInfo"作为字符串传递给它。但是ListBox的内部代码足够聪明,可以将此字符串用作与实际值的映射

答案 1 :(得分:1)

  

为什么我们不简单地执行Results.DisplayMember = Person.FullInfo?

这会将DisplayMember的值设置为FullInfo返回的字符串。值DisplayMember是保存要显示的值的属性的名称。

您可以通过以下方式进行设置,这是我的建议:

Results.DataSource = people;
Results.DisplayMember = nameof(person.FullInfo);

答案 2 :(得分:1)

ListBox在显示其数据源中的数据时在内部使用Reflection。在C#中,反射是一种功能强大的机制,您可以通过仅将字段的 name 作为字符串来访问对象字段。

您可以尝试使用以下代码段进行反射:

var person = new Person{First_Name = "FirstName", Last_Name="LastName", Person_ID=12, EmailAddress="email@email.com"};
var fullInfo = person.GetType().GetProperty("FullInfo").GetValue(person, null);