2010-06-23 16 views
5

Tengo dos objetos MetaItems y elementos.C# genéricos y colección

MetaItem es una plantilla para objetos y Elementos contiene valores reales. Por ejemplo, "Departamento" se trata como meta-elemento y "Ventas", "Región de Reino Unido", "Región de Asia" se tratan como elementos.

Además, deseo mantener la relación padre-hijo en estos meta-elementos y elementos.

He siguiente código para la misma -

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace WpfApplication12 
{ 
    public interface IEntity 
    { 
     int Id { get; set; } 

     string Name { get; set; } 
    } 

    public interface IHierachy<T> 
    { 
     IHierachy<T> Parent { get; } 

     List<IHierachy<T>> ChildItems { get; } 

     List<IHierachy<T>> LinkedItems { get; } 

    } 

    public class Entity : IHierachy<IEntity>, IEntity 
    { 

     #region IObject Members 

     private int _id; 
     public int Id 
     { 
      get 
      { 
       return _id; 
      } 
      set 
      { 
       _id = value; 
      } 
     } 

     private string _name; 

     public string Name 
     { 
      get 
      { 
       return _name; 
      } 
      set 
      { 
       _name = value; 
      } 
     } 

     #endregion 

     #region IHierachy<IEntity> Members 

     public IHierachy<IEntity> _parent; 
     public IHierachy<IEntity> Parent 
     { 
      get 
      { 
       return _parent; 
      } 
     } 

     private List<IHierachy<IEntity>> _childItems; 

     public List<IHierachy<IEntity>> ChildItems 
     { 
      get 
      { 
       if (_childItems == null) 
       { 
        _childItems = new List<IHierachy<IEntity>>(); 
       } 
       return _childItems; 
      } 
     } 

     private List<IHierachy<IEntity>> _linkedItems; 

     public List<IHierachy<IEntity>> LinkedItems 
     { 
      get 
      { 
       if (_linkedItems == null) 
       { 
        _linkedItems = new List<IHierachy<IEntity>>(); 
       } 
       return _linkedItems; 
      } 
     } 
     #endregion 
    } 


    public class Item : Entity 
    { 
    } 

    public class MetaItem : Entity 
    { 
    } 

} 

Siguiendo es mi clase de prueba -

public class Test 
{ 
    public void Test1() 
    { 
     MetaItem meta1 = new MetaItem() { Id = 1, Name = "MetaItem1"}; 

     MetaItem meta2 = new MetaItem() { Id = 1, Name = "MetaItem 1.1"}; 

     Item meta3 = new Item() { Id = 101, Name = "Item 1" }; 


     **meta1.ChildItems.Add(meta3);** // this line should not compile. 
     meta1.ChildItems.Add(meta2) // This is valid and gets compiled. 
    } 
} 

En la clase de prueba, cuando estoy y búsqueda de relación padre-hijo, puedo añadir el artículo como un objeto hijo para el objeto meta-elemento. Aquí quiero que se genere un error de compilación.

¿Alguien puede ayudarme a lograr esto.

-Regards Raj

+0

Si un meta-elemento es solo un elemento que contiene otros elementos, ¿no es realmente sólo un artículo de todos modos, donde 'T = Item'? –

+2

No relacionado con su pregunta, pero para Entity.Id y Name, las propiedades implementadas automáticamente son su amigo. – dahlbyk

Respuesta

0

¿Por qué no pensar que la línea debería compilar? Parece completamente válido.

La lista de elementos del niño es pública. Si no desea que se puedan agregar a la lista, deberá envolver su propia colección o usar el ReadOnlyCollection<IHierachy<IEntity>>.

Oh, usted ha solucionado su pregunta. Creo que la solución es hacer que la clase Entity sea genérica.

using System.Collections.Generic; 

namespace WpfApplication12 
{ 
    public interface IEntity 
    { 
     int Id { get; set; } 
     string Name { get; set; } 
    } 

    public interface IHierachy<T> 
    { 
     IHierachy<T> Parent { get; } 
     List<IHierachy<T>> ChildItems { get; } 
     List<IHierachy<T>> LinkedItems { get; } 
    } 

    public class Entity<T> : IHierachy<T>, IEntity 
    { 
     private int _id; 
     public int Id 
     { 
      get { return _id; } 
      set { _id = value; } 
     } 

     private string _name; 
     public string Name 
     { 
      get { return _name; } 
      set { _name = value; } 
     } 

     public IHierachy<T> _parent; 
     public IHierachy<T> Parent 
     { 
      get 
      { 
       return _parent; 
      } 
     } 

     private List<IHierachy<T>> _childItems; 
     public List<IHierachy<T>> ChildItems 
     { 
      get 
      { 
       if(_childItems == null) 
       { 
        _childItems = new List<IHierachy<T>>(); 
       } 
       return _childItems; 
      } 
     } 

     private List<IHierachy<T>> _linkedItems; 
     public List<IHierachy<T>> LinkedItems 
     { 
      get 
      { 
       if(_linkedItems == null) 
       { 
        _linkedItems = new List<IHierachy<T>>(); 
       } 
       return _linkedItems; 
      } 
     } 
    } 


    public class Item : Entity<Item> 
    { 
    } 

    public class MetaItem : Entity<MetaItem> 
    { 
    } 

    public class Test 
    { 
     public void Test1() 
     { 
      MetaItem meta1 = new MetaItem() { Id = 1, Name = "MetaItem1"}; 
      MetaItem meta2 = new MetaItem() { Id = 1, Name = "MetaItem 1.1"}; 
      Item meta3 = new Item() { Id = 101, Name = "Item 1" }; 

      meta1.ChildItems.Add(meta3); // this line should not compile. 
      meta1.ChildItems.Add(meta2); // This is valid and gets compiled. 
     } 
    } 

} 
+0

Creo que no quiere permitir que se agregue Item como elemento secundario de MetaItem (aunque por código, ambos son de tipo Entidad). En otras palabras, solo MetaItem.ChildItems solo debe contener otros MetaItem. No estoy familiarizado con las cosas de Entity, así que supongo que sería ChildItem para ser una lista de MetaItems ... – Alan

+0

Ah, sí, ha solucionado la pregunta y estás en lo cierto. Debería hacer que las entidades/jerarquías sean más genéricas. Estoy arreglando mi solución ahora. –

3

El código está compilando porque habrá ChildItemsIList<Entity>, que incluye tanto Item y MetaItem. Si se va a hacer Entity genérica:

public class Entity<T> : IHierachy<T>, IEntity where T : IEntity { ... } 

allí tendría que definir Item y MetaItem así:

public class Item : Entity<Item> { } 

public class MetaItem : Entity<MetaItem> { } 

en cuyo caso su ChildItems sería de la correcta, más restringida, tipo.

+0

Ok, lo hice funcionar, después de cambiar las referencias a 'IEntity' dentro de' Entity 'a' T'. Heredar una especialización en ti es una técnica interesante. –

+0

Sí, completar el cambio 'Entity ' se dejó como ejercicio. :) Definitivamente una técnica útil para escenarios específicos. – dahlbyk

+0

Hola dahlbyk, Ya. Agregar los cambios necesarios con los anteriores cambia su funcionamiento perfecto. Gracias. – Raj