一般的なスケジューラデータをC#に保存するための理想的なデータ構造/手法


8

HTMLでテーブルを出力する汎用スケジューラオブジェクトをC#4で実装しようとしています。基本的な目的は、いくつかのオブジェクトをさまざまな属性と一緒に表示し、特定の期間に何かを実行していたかどうかを示すことです。

スケジューラーはヘッダーを表示するテーブルを出力します:

Detail Field 1 ....N| Date1.........N

日付範囲を作成するために、開始日と終了日でテーブルを初期化したいと思います(理想的には、時間などの他の期間も実行できますが、それは重要ではありません)。次に、関連するイベントを持つ汎用オブジェクトを提供します。

テーブルセルにマークを付けたい期間内にオブジェクトにイベントがある場合

例えば

Name Height Weight 1/1/2011 2/1/2011 3/1/20011...... 31/1/2011
Ben  5.11    75       X        X                       X
Bill 5.7     83                X        X

だから私は開始日= 1/1/2011と終了日31/1/2011でスケジューラを作成しました

人物オブジェクト(既にソートされている)を指定して、表示するフィールド(名前、高さ、体重)を伝えたい

各人には、開始日と終了日があるイベントがあります。一部のイベントは開始して終了しますが、関連する日付などに表示されるはずです。

理想的には、クラス予約オブジェクトなども提供できるようにしたいと考えています。だから私はそれを一般的に保つようにしています。

私は同様のJavasript実装などを見てきました。

これに適したデータ構造は何でしょうか?それを一般的にするために使用できるテクニックについての考え。私はジェネリックスに不慣れなので、どんなヒントも歓迎されます。


ジェネリックスでは、タイプセーフにするために基本クラスまたはインターフェースが必要です。リフレクションを使用して実行時にプロパティを取得できますが、これは遅く、実行時にのみスローされます
Firo

ええ、データ構造の基本クラスには、サイドカラムヘッダー(1からnの場合があります)を保持するある種の構造と、メインカラムヘッダー(時間と同じくらい大きい)を保持するある種の構造があると期待していましたピリオド)、そして実際の行を保持する構造。一般的な部分は、私は、私はなどのために必要な列を定義しているいくつかのランダムなオブジェクトを渡すと定義する能力だった
GraemeMiller

このタスクに「動的」キーワードを使用することを考えたことはありますか?
Dimi Takis

1
データを中心とした設計に関するこの興味深い議論は、方向性やインスピレーションを与えるかもしれません。
TheSilverBullet 2012

フィールドデータ(高さ、重みなど)で実際の操作を行う必要がない場合は、スタックオーバーフローのこの回答で概説されているリフレクションを使用して、オブジェクトから表示するプロパティ値と名前を取得できます。
nemec

回答:


2

難しいとは思いません。何が欠けていますか?

using System;
using System.Collections.Generic;

public class ScheduledPerson {
    public string Name {get; set;}

    public Dictionary<string, Object> Fields {
        get { return _fields; }
        set { _fields = value; }
    }
    private Dictionary<string, Object> _fields = new Dictionary<string, Object>();

    public List<Tuple<DateTime, DateTime>> Events {
        get { return _events; }
        set { _events = value; }
    }
    private List<Tuple<DateTime, DateTime>> _events = new List<Tuple<DateTime, DateTime>>();

    public ScheduledPerson(string name){
        Name = name;
    }
}

フィールドは何でもかまいませんので、ScheduledPersonクラスをジェネリックにする良い方法はありません。フィールド値をオブジェクトとして保存しています。これは、フィールド値をダイナミクスにする必要がないためです。すべてのフィールド値タイプに適切なToString()実装があることを確認してください。

イベントをタプルではなく、DateRangeまたは独自のイベントクラスのリストにしたい場合は、自由にご利用ください。

次に、すべてのScheduledPersonレコードからすべてのヘッダーを理解するとともに、テーブル内の各ScheduledPersonをレンダリングする個別のクラスを作成する必要があります。あなたが1万人を扱っている場合、すべてのヘッダーが格納されているより良いソリューションが必要ですが、ほとんどのアプリケーションでは、すべてのScheduledPersonのすべてのフィールドを列挙してヘッダーを理解することは悪くありません。


0

一般的に、表示したい方法に基づいてソリューションのデータを保存することはありません。これは、ニーズが変化したときに事態を困難にする非常に具体的なソリューションにつながります。ソリューションのエンティティの観点から物事を分解し、レポートを生成するときに表示データを生成するLINQクエリのセットを作成します。

以下のコードはすべて構造化されており、初期化などを省略しています。

public class Person
{
   public string Name {get;set;}
   public double Height {get;set;}
   public double Weight {get;set;}
}

public class ScheduledEvent
{
   public Person Attendee {get;set;}
   public DateTime EventDate {get;set;}
}

public class Schedule
{
   public DateTime StartDate {get;set; }
   public DateTIme EndDate {get;set;}
   List<Person> Persons {get;set;}
   List<ScheduledEvent> SheduledEvents {get;set;}
}

さて、実際には、これらをある種のデータベースに格納し、NHibernateやEntity Frameworkなどを使用して、実行時にすべてのクエリを実行します。ただし、インメモリデモの目的では、テーブル行を生成するクエリは次のようになります。

class TableRow
{
   string Name { get;set; }
   string Height {get;set; }
   string Weight {get;set; }
   List<string> DatesWithEvents {get; }
}

var columns = List<string>{ "Name", "Height", "Weight", }.Concat(
                schedule.ScheduledEvents
                  .Select(e=> e.EventDate.ToShortDate())
                  .Distinct())
              .ToList();
var rows = new List<TableRow>();

foreach(var p in schedule.Persons) 
{
   var row = new TableRow();
   row.Name = p.Name;
   row.Height = p.Height;
   row.Weight = p.Weight;
   row.DatesWithEvents = schedule.ScheduledEvents
     .Where(e => e.Person == p)
     .Select(e => e.EventDate.ToShortDate()).Distinct().ToList();
   rows.Add(row);
}    

次に、レンダラーで列を一致させて、「X」を貼り付けて日付が入力されたことをマークする場所を確認します。さらに努力すれば、これをより洗練されたソリューションにリファクタリングできますが、これが基本です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.