Struttura dati / tecniche ideali per la memorizzazione di dati generici dello scheduler in C #

8

Sto cercando di implementare un oggetto scheduler generico in C # 4 che genererà una tabella in HTML. Lo scopo di base è mostrare alcuni oggetti insieme a vari attributi e se stia facendo qualcosa in un determinato periodo di tempo.

Lo scheduler mostrerà una tabella che mostra le intestazioni:

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

Voglio inizializzare la tabella con una data di inizio e una data di fine per creare l'intervallo di date (idealmente potrebbe anche fare altri periodi di tempo, ad esempio ore ma ciò non è fondamentale). Quindi voglio fornire un oggetto generico che abbia eventi associati.

Dove un oggetto ha eventi nel periodo in cui voglio che una cella di tabella sia contrassegnata

per es.

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

Quindi ho creato lo scheduler con Data di inizio = 1/1/2011 e data di fine 31/1/2011

Mi piacerebbe dargli il mio oggetto person (già ordinato) e dirgli quali campi voglio mostrare (Nome, Altezza, Peso)

Ogni persona ha eventi che hanno una data di inizio e una data di fine. Alcuni eventi inizieranno e finiranno in modo esterno ma dovrebbero comunque essere mostrati nella data pertinente ecc.

Idealmente mi piacerebbe essere stato in grado di fornirgli anche un oggetto per le prenotazioni di classe. Quindi sto cercando di tenerlo generico.

Ho visto implementazioni di Javasript ecc. simili.

Quale sarebbe una buona struttura dati per questo? Qualche idea sulle tecniche che potrei usare per renderla generica. Non sono eccezionale con i generici, quindi ogni suggerimento è stato apprezzato.

    
posta GraemeMiller 09.12.2011 - 15:21
fonte

2 risposte

2

Non penso che sia troppo difficile. Cosa mi manca?

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;
    }
}

Non vedo un buon modo per rendere generiche le nostre classi ScheduledPerson, in quanto sembra che i campi possano essere qualsiasi cosa. Sto memorizzando i valori del campo come oggetti, poiché non vedo nulla che li richieda per essere dinamici. Assicurati solo che tutti i tipi di valori di campo abbiano un'implementazione ToString () ragionevole.

Se vuoi che gli eventi siano un elenco di DateRange o della tua classe Event anziché di Tuple, sentiti libero.

Rimane quindi il compito di scrivere una classe separata per il rendering di ogni ScheduledPerson in una tabella, oltre a trovare tutte le intestazioni da tutti i record ScheduledPerson. Hai a che fare con diecimila persone, vorrai una soluzione migliore che abbia tutte le intestazioni memorizzate, ma per la maggior parte delle applicazioni, non sarà troppo brutto enumerare tutti i Field su tutti i ScheduledPerson per capire le intestazioni.

    
risposta data 30.11.2014 - 21:26
fonte
0

In generale, non memorizzerei i dati per la tua soluzione in base al modo in cui desideri visualizzarli. Ciò porta a soluzioni molto specifiche che renderanno le cose difficili quando le vostre esigenze cambiano. Vorrei spezzare le cose in termini di entità nella soluzione e quindi creare una serie di query LINQ che genererebbero i dati di visualizzazione quando è il momento di generare il report.

Tutto il codice seguente è strutturale e omettente l'inizializzazione, ecc.

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;}
}

Ora, in pratica, li memorizzerei in un database di qualche tipo e faccio tutte le query in fase di esecuzione con qualcosa come NHibernate o Entity Framework. Ma per scopi dimostrativi in memoria, le query per produrre le tue linee di tabella sarebbero le seguenti:

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);
}    

Quindi nel tuo renderer, abbina le colonne per sapere dove incollare la "X" per contrassegnare che la data è piena. Con uno sforzo maggiore, puoi refactoring in una soluzione molto più elegante, ma questa è la base.

    
risposta data 18.12.2014 - 18:37
fonte

Leggi altre domande sui tag