Estructura / técnicas de datos ideales para almacenar datos genéricos del programador en C #

8

Estoy intentando implementar un objeto de planificador genérico en C # 4 que generará una tabla en HTML. El objetivo básico es mostrar algún objeto junto con varios atributos, y si estaba haciendo algo en un período de tiempo determinado.

El programador generará una tabla con los encabezados:

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

Quiero inicializar la tabla con una fecha de inicio y una fecha de finalización para crear el rango de fechas (idealmente, también podría hacer otros períodos de tiempo, por ejemplo, horas, pero eso no es vital). Luego quiero proporcionar un objeto genérico que tendrá eventos asociados.

Cuando un objeto tenga eventos dentro del período, quiero que se marque una celda de tabla

Por ejemplo,

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

Así que creé el programador con Fecha de inicio = 1/1/2011 y fecha de finalización 31/1/2011

Me gustaría asignarle mi objeto personal (ya clasificado) y decirle qué campos quiero que se muestren (Nombre, Altura, Peso)

Cada persona tiene eventos que tienen una fecha de inicio y una de finalización. Algunos eventos comenzarán y finalizarán, pero aún deben mostrarse en la fecha correspondiente, etc.

Idealmente, me gustaría haber sido capaz de proporcionarle, por ejemplo, un objeto de reserva de clase también. Así que estoy tratando de mantenerlo genérico.

He visto implementaciones de Javasript, etc. similares.

¿Cuál sería una buena estructura de datos para esto? Cualquier reflexión sobre las técnicas que podría usar para hacerla genérica. No soy muy bueno con los genéricos, así que aprecio cualquier consejo.

    
pregunta GraemeMiller 09.12.2011 - 15:21

2 respuestas

2

No creo que esto sea demasiado difícil. ¿Qué me estoy perdiendo?

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

No veo una buena manera de hacer que nuestras clases ScheduledPerson sean genéricas, ya que parece que los campos pueden ser cualquier cosa. Estoy almacenando los valores de campo como Objetos, ya que no veo nada que requiera que sean dinámicos. Solo asegúrese de que todos los tipos de valor de campo tengan una implementación de ToString () sensata.

Si desea que los Eventos sean una Lista de DateRange o de su propia clase de Evento en lugar de Tuple, siéntase libre.

Luego, le queda a usted escribir una clase separada para representar cada ScheduledPerson en una tabla, junto con el cálculo de todos los encabezados de todos los registros de ScheduledPerson. Si está tratando con diez mil personas, querrá una mejor solución que tenga todos los encabezados almacenados, pero para la mayoría de las aplicaciones, no será tan malo enumerar todos los Campos en todas las Personas Programadas para averiguar los encabezados.

    
respondido por el Patrick Szalapski 30.11.2014 - 21:26
0

En general, no almacenaría los datos de su solución según la forma en que desee mostrarlos. Eso lleva a soluciones muy específicas que dificultarán las cosas cuando cambien sus necesidades. Desglosaría las cosas en términos de entidades en su solución y luego crearía un conjunto de Consultas LINQ que generarían sus datos de visualización cuando sea el momento de generar el informe.

Todo el código a continuación es estructural y omite la inicialización, etc.

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

Ahora, en la práctica, los almacenaría en una base de datos de algún tipo y haría todas las consultas en tiempo de ejecución con algo como NHibernate o Entity Framework. Pero para fines de demostración en memoria, las consultas para producir las líneas de su tabla serían como las siguientes:

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

Luego, en su renderizador, solo haga coincidir las columnas para saber dónde pegar la 'X' para marcar que la fecha está llena. Con más esfuerzo, puede refactorizar esto en una solución mucho más elegante, pero esto es lo básico.

    
respondido por el Steve Mitcham 18.12.2014 - 18:37

Lea otras preguntas en las etiquetas