c#:将不同的类解析为对象,并以相同的方式显示属性值

本文关键字:方式 显示 属性 对象 | 更新日期: 2023-09-27 18:12:27

我在c#控制台应用程序中有几个类。

public class Cars:List<Car>
{}

:

public class Drivers:List<Driver>
{}

目标是始终以相同的方式呈现控制台输出,无论carsdrivers是否被解析为呈现方法。所以参数类型为object。当然,属性可以有不同的名称。

输出应该像这样:

// Cars
Brand HP  Topspeed
VW    100 200
VW    90  150

// Drivers
Name Age Sex 
Pit  18  m
Jane 20  f

所以我需要读取属性名以使它们成为列标题,然后读取每个对象的值。我已经搜索了一段时间,总是出现这样的东西:

public static void RenderOutput(object obj)
{
    foreach (var prop in obj.GetType().GetProperties())
    {
    }
}

虽然在运行时鼠标悬停在obj上显示所有所需的对象和属性(品牌,HP,大众,100,…)非常好,但我无法通过cardriverprop项目car中挤出driver的值。

任何建议吗?谢谢jimbo2015

c#:将不同的类解析为对象,并以相同的方式显示属性值

我建议去interface路由,有一个接口,将有方法RenderOutput。汽车和驾驶员都将实现该接口,并提供它们自己的方法实现。这将是更合适的,因为汽车方法将不知道司机或签证-verse。在调用方法时,不是传递对象,而是调用实例方法。

在使用反射时应该使用BindingFlags,以便获得实例的属性。例如,要获取object o的所有private属性,您应该使用:

IEnumerable<PropertyInfo> props = o.GetType().GetProperties(BindingFlags.Instance | BindingFlags.NonPublic);
foreach (PropertyInfo info in props)
{
    Console.WriteLine(info.Name + info.GetValue(o));
}

说了这些之后,请注意,为打印方法使用CarDriver实现的interface可能是更正确的设计。如果您想使用反射,我建议在您想要打印的属性上添加Attributes,并使用所需的显示名称,以便将显示与代码的命名约定分开。

正确的方法是实现一个接口(如@Adarsha所说),并在每个类中实现RenderOutput()方法,使其具有自己的特定实现,具有正确的属性列表,正确的格式等。

现在,如果你仍然想坚持你的方法,这是可行的。

让我们假设这些是你的类

public class Car
{
    public string Brand { get; set; }
    public int HorsePower { get; set; }
    public int TopSpeed { get; set; }
}
public class Driver
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Sex { get; set; }
}

现在,这些方法将使用反射来读取属性并在控制台中写入它们。

public static void RenderOutput(IEnumerable<object> collection)
{
    RenderHeader(collection.First()); //collection not validated
    collection.ToList().ForEach(item => RenderBody(item));
}
private static void RenderHeader(object obj)
{
    var properties = obj.GetType().GetProperties().OrderBy(p => p.Name);
    Console.WriteLine("");
    foreach (var prop in properties)
    {
        Console.Write(prop.Name + "'t"); //or ("{0,15}", prop.Name)
    }
}
private static void RenderBody(object obj)
{
    var properties = obj.GetType().GetProperties().OrderBy(p => p.Name);
    Console.WriteLine("");
    foreach (var prop in properties)
    {
        Console.Write((prop.GetValue(obj, null)) + "'t"); //or ("{0,15}", (prop.GetValue(obj, null)))
    }
}

您现在可以在任何IEnumerable<T>上调用RenderOutput()方法来获得所需的输出。你可以像这样测试

static void Main(string[] args)
{
    //test data
    var cars = new List<Car>();
    cars.Add(new Car { Brand = "BMW", HorsePower = 100, TopSpeed = 200 });
    cars.Add(new Car { Brand = "VW", HorsePower = 90, TopSpeed = 150 });
    var drivers = new List<Driver>();
    drivers.Add(new Driver { Name = "Prit", Age = 18, Sex = "Male" });
    drivers.Add(new Driver { Name = "Jane", Age = 20, Sex = "Female" });
    RenderOutput(cars);
    Console.WriteLine();
    RenderOutput(drivers);
    Console.ReadLine();
}

这是生成的输出:

Brand   HorsePower      TopSpeed
BMW     100     200
VW      90      150
Age     Name    Sex
18      Prit    Male
20      Jane    Female

注意:这对复杂类型的属性不起作用!