首页 > 解决方案 > 如何从共享同一接口的对象列表中访问对象的特定属性

问题描述

我有一个应用程序,我说 10 个不同类型的对象。我希望将它们放在同一个列表中并在很多情况下遍历它们。我不能将它们推入一个列表,因为它们属于不同类型。所以我创建了一个接口并创建了一个所有对象共享的属性。现在我有了对象列表,列表的类型是“接口”。当我遍历对象时,我无法访问对象的特定属性,因为编译器只会在运行时知道它是什么对象。因此,如果我尝试对 Object_A.Name 进行编码,Visual Studio 将显示错误,因为它不知道它们的对象类型。我显然可以做一个 if else 或类似的事情来找到对象的类型并转换它,但我想知道有更好的方法,

在下面的代码中,我想获取 Devname,但我不能,因为它不是接口的一部分,而是属于每个对象。我可以让它成为界面的一部分,但我可能时不时需要获取一个特定的属性。因此想知道是否有办法做到这一点。

foreach (ICommonDeviceInterface device in Form1.deviceList)
{
if (device.DevName.Equals(partnername))
{
return device.Port[portNo].PortRef;
}
}

标签: c#

解决方案


您可以做到这一点的一种方法是使用反射尝试从对象中获取命名属性的属性值,使用如下辅助方法:

public static object GetPropValue(object src, string propName)
{
    return src?.GetType().GetProperty(propName)?.GetValue(src, null);
}

上述代码的功劳归于:使用 C# 中的反射从字符串中获取属性值

这不需要检查类型或强制转换,它只返回属性的值,或者null如果它不包含该属性。

在使用中它可能看起来像:

private static void Main()
{
    // Add three different types, which all implement the same interface, to our list
    var devices = new List<ICommonDeviceInterface>
    {
        new DeviceA {DevName = "CompanyA", Id = 1},
        new DeviceB {DevName = "CompanyB", Id = 2},
        new DeviceC {Id = 3},
    };

    var partnerName = "CompanyB";

    foreach (var device in devices)
    {
        // Try to get the "DevName" property for this object
        var devName = GetPropValue(device, "DevName");

        // See if the devName matches the partner name
        if (partnerName.Equals(devName))
        {
            Console.WriteLine($"Found a match with Id: {device.Id}");
        }
    }
}

用于上述示例的类:

interface ICommonDeviceInterface
{
    int Id { get; set; }
}

class DeviceA : ICommonDeviceInterface
{
    public int Id { get; set; }
    public string DevName { get; set; }
}

class DeviceB : ICommonDeviceInterface
{
    public int Id { get; set; }
    public string DevName { get; set; }
}

class DeviceC : ICommonDeviceInterface
{
    public int Id { get; set; }
}

推荐阅读