2010-06-23 18 views
5

Mam dwa obiekty MetaItems and Items.C# generics and collection

MetaItem jest szablonem dla obiektów, a element zawiera rzeczywiste wartości. Na przykład "Dział" jest traktowany jako meta-przedmiot, a "Sprzedaż", "Region Wielkiej Brytanii", "Region Azji" są traktowane jak przedmioty.

Dodatkowo chcę zachować relację rodzic-dziecko na tych metatrybutach i przedmiotach.

Mam następujący kod do samo -

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

} 

Poniżej moja klasa testu -

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

W klasie testowej, kiedy jestem buidling relacji rodzic-dziecko, mogę dodać element jako obiekt podrzędny dla obiektu meta-item. Tutaj chcę wygenerować błąd kompilacji.

Czy ktoś może mi pomóc w osiągnięciu tego.

-Regards Raj

+0

Jeśli meta element jest tylko elementem zawierającym inne elementy, to czy tak naprawdę nie jest to tylko element , gdzie 'T = Element'? –

+2

Niezwiązane z twoim pytaniem, ale w przypadku Entity.Id i Name, automatycznie wdrożone właściwości są twoimi przyjaciółmi. – dahlbyk

Odpowiedz

0

Dlaczego nie sądzisz, że wiersz powinien skompilować? Wygląda całkowicie poprawne.

Lista ChildItems jest publiczna. Jeśli nie chcesz, aby można było dodać do listy, musisz owinąć własną kolekcję lub użyć numeru ReadOnlyCollection<IHierachy<IEntity>>.

Naprawiłeś swoje pytanie. Myślę, że rozwiązaniem jest stworzenie klasy Entity.

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

Myślę, że nie chce dopuścić do dodawania elementu jako elementu potomnego MetaItem (mimo że kod jest mądry, oba są typu Entity). Innymi słowy, tylko MetaItem.ChildItems powinien zawierać tylko inne MetaItem. Nie jestem zaznajomiony z tematem Entity, więc zgaduję, że zmieniam ChildItem na listę MetaItems ... – Alan

+0

Ach, tak, naprawił to pytanie i jesteś całkowicie poprawny. Musisz uczynić Jednostki/Hierachies bardziej ogólnymi. Naprawiam teraz moje rozwiązanie. –

3

Kod kompiluje ponieważ ChildItems będzie IList<Entity>, która obejmuje zarówno Item i MetaItem. Jeśli było zrobić Entity Generic:

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

Wtedy można zdefiniować Item i MetaItem takiego:

public class Item : Entity<Item> { } 

public class MetaItem : Entity<MetaItem> { } 

W takim przypadku ich ChildItems byłoby prawidłowe, bardziej ograniczony, typu.

+0

Ok, mam go do pracy, po zmianie odniesień do 'IEntity' wewnątrz' Entity 'na' T'. Dziedziczenie specjalizacji na sobie jest interesującą techniką. –

+0

Tak, ukończenie zmiany 'Entity ' zostało pozostawione jako ćwiczenie. :) Zdecydowanie przydatna technika do konkretnych scenariuszy. – dahlbyk

+0

Witaj dahlbyk, Ya. Dodanie koniecznych zmian z powyższymi zmianami powoduje, że działa idealnie. Dzięki. – Raj