2012-01-12 9 views
5

Necesito filtrar y solicitar entradas de datos después de los criterios que un usuario selecciona a través de un menú desplegable. Seleccionables serán cosas como "entradas más nuevas primero", "entradas más antiguas primero", "el precio más bajo primero", etc.¿Qué patrón de diseño para ordenar y filtrar datos?

Podría simplemente crear una enumeración para las opciones y cambiar/caso en que recupere los datos, pero me ' más bien hacer esto de una manera fácilmente extensible.

¿Qué patrón de diseño se ajusta mejor a la situación?

+1

winforms, wpf, silverlight, webforms o mvc? –

+1

Supongo que el patrón de ESTRATEGIA haría ... – VS1

+1

WebForms, pero ¿no es un problema genérico? – magnattic

Respuesta

3

Todo el mundo ha mencionado el patrón de estrategia. Solo pensé en publicar mi implementación simple. No hay necesidad de hacerlo más complicado de lo necesario.

public enum SortMethod 
{ 
    Newest, 
    Oldest, 
    LowestPrice, 
} 

public class Foo 
{ 
    public DateTime Date {get;set;} 
    public decimal Price {get;set;} 
} 


... 
var strategyMap = new Dictionary<SortMethod, Func<IEnumerable<Foo>, IEnumerable<Foo>>> 
        { 
         { SortMethod.Newest, x => x.OrderBy(y => y.Date) }, 
         { SortMethod.Oldest, x => x.OrderByDescending(y => y.Date) }, 
         { SortMethod.LowestPrice, x => x.OrderBy(y => y.Price) } 
        }; 

... 
var unsorted = new List<Foo> 
       { 
        new Foo { Date = new DateTime(2012, 1, 3), Price = 10m }, 
        new Foo { Date = new DateTime(2012, 1, 1), Price = 30m }, 
        new Foo { Date = new DateTime(2012, 1, 2), Price = 20m } 
       }; 

var sorted = strategyMap[SortMethod.LowestPrice](unsorted); 
+0

funciona muy bien para mí, elegante y simple. ¡Gracias! – magnattic

0

No siempre soy bueno al nombrar el patrón adecuado para mi pensamiento, pero mi pensamiento inicial es por qué no hacer una clase simple para cada opción e implementar IComparer (T) y luego cargar esos elementos como sus opciones desplegables. Es probable que solo necesite una propiedad de nombre además del método de interfaz.

public class NameSorter: IComparer<WhateverObj> 
{ 
public String DisplayName;  

public int Compare(WhateverObj x, WhateverObj y) 
{ 

} 
} 
0

Como se mencionó en los comentarios, esto suena como un trabajo para el Strategy pattern. Lo reconocerá ya que esto ya se encuentra fuertemente en el framework .NET.

Aquí hay un ejemplo usando IComparer, o usando los métodos de extensión LINQ en 3.5 que prefiero. Deberá agregar un método de fábrica a la clase base que determine qué comparador debería usar, o puede almacenarlo como parte de los datos en la lista desplegable.

static void Main(string[] args) 
{ 

    List<User> users = new List<User>(); 
    users.Add(new User() { Name = "Larry", Age = 35 }); 
    users.Add(new User() { Name = "Bob", Age = 25 }); 
    users.Add(new User() { Name = "Brian", Age = 30 }); 

    NameComparer sorter = new NameComparer(); 
    IEnumerable<User> sortedUsers = sorter.Sort(users); 

    NameComparer35 sorter35 = new NameComparer35(); 
    IEnumerable<User> sortedUsers35 = sorter35.Sort(users); 
} 

public abstract class MyComparer<T> : IComparer<T> where T: User 
{ 
    public abstract int Compare(T x, T y); 

    public IEnumerable<T> Sort(IEnumerable<T> items) 
    { 
     items.ToList().Sort(this); 
     return items; 
    } 
} 

public abstract class MyComparer35<T> where T : User 
{ 
    public abstract IEnumerable<T> Sort(IEnumerable<T> items); 
} 

public class NameComparer35 : MyComparer35<User> 
{ 
    public override IEnumerable<User> Sort(IEnumerable<User> items) 
    { 
     return items.OrderBy(u => u.Name); 
    } 
} 

public class NameComparer : MyComparer<User> 
{ 
    public override int Compare(User x, User y) 
    { 
     return x.Name.CompareTo(y.Name); 
    } 
} 

public class AgeComparer : MyComparer<User> 
{ 
    public override int Compare(User x, User y) 
    { 
     return x.Age.CompareTo(y.Age); 
    } 
} 

public class User 
{ 
    public string Name { get; set; } 
    public int Age { get; set; } 

    public override string ToString() 
    { 
     return string.Format("{0} {1}", Name, Age); 
    } 
} 
Cuestiones relacionadas