2

C# コンソール アプリケーションにはいくつかのクラスがあります。

public class Cars:List<Car>
{}

と:

public class Drivers:List<Driver>
{}

目標は、コンソール出力を常に同じ方法でレンダリングすることです。レンダリング方法に解析されるかどうcarsかは関係ありません。driversしたがって、パラメーターのタイプは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())
    {
    }
}

実行時にマウスオーバーすると、必要なすべてのオブジェクトとプロパティ (ブランド、HP、VW、100、...) が非常によく表示されますが、またはによって項目objから値を絞り出すことができません。propcarcardriverdriver

なにか提案を?Thx jinbo2015

4

3 に答える 3

2

route に行くことをお勧めします。 interfacemethod を持つインターフェースを持っています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()これで、任意のメソッドを呼び出して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に実装される which を持つことは、おそらく設計上より正しいことに注意してください。とにかくリフレクションを使用したい場合は、コードの命名規則から表示を分離するために、印刷するプロパティに目的の表示名を追加することをお勧めします。CarDriverAttributes

于 2015-09-13T08:42:28.740 に答える