2

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

public class Cars:List<Car>
{}

和:

public class Drivers:List<Driver>
{}

cars目标是始终以相同的方式呈现控制台输出,无论是否drivers解析为呈现方法都无关紧要。所以参数是 type 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())
    {
    }
}

尽管在运行时 mouseoverobj可以很好地显示所有所需的对象和属性(Brand、HP、VW、100、...),但我无法将值从propitem carbycardriverby挤出driver

有什么建议吗?谢谢 jimbo2015

4

3 回答 3

2

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

于 2015-09-13T08:17:37.150 回答
1

正确的方法是实现一个接口(正如@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)))
    }
}

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

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

注意:这不适用于复杂类型的属性!

于 2015-09-13T09:01:29.063 回答
1

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

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

话虽如此,请注意拥有一个interface将由打印方法实现CarDriver用于打印方法的设计可能更正确。如果您无论如何都想使用反射,我建议Attributes您在要打印的属性上添加所需的显示名称,以便将显示与代码的命名约定分开。

于 2015-09-13T08:42:28.740 回答