Domanda

Non sono sicuro se c'è già una nomenclatura per questo, ma per il bene di questa domanda permette di definire due termini: pari applicazione o annidati applicazione per illustrare come di implementare le classi di raccolta in un modello di dati che contiene molte relazioni di entità genitore / figlio.

Io uso il termine pari a descrivere lo scenario in cui si sceglie di implementare le classi di raccolta nel vostro livello di modello lungo il lato con le classi di entità sostanzialmente rendendoli coetanei nella vostra API in questo modo:

public class ParentEntity
{
  private ChildEntityCollection children;
}

public class ChildEntity
{
}

public class ChildEntityCollection : ICollection<ChildEntity>
{
}

Il vantaggio principale è che è possibile riutilizzare la classe di raccolta in altre classi di entità che capita di memorizzare figli dello stesso tipo.

Io uso il termine nidificato per descrivere lo scenario in cui li si implementa come una classe annidata in questo modo:

public class ParentEntity
{
  private ChildEntityCollection children;

  public class ChildEntityCollection : ICollection<ChildEntity>
  {
  }
}

public class ChildEntity
{
}

Il vantaggio principale è che ogni genitore può implementare la propria classe di raccolta per archiviare i propri figli in modo che è più ottimizzato per quel genitore specifica. Per esempio, una controllante può trovare che un array funziona bene mentre un altro può utilizzare un albero splay (oscura lo so, ma illustra bene il mio punto).

Ho notato che Microsoft utilizza entrambi i modi di dire nei vari quadri relativi .NET. Lo spazio dei nomi System.Windows.Forms sembra basarsi pesantemente su implementazioni nidificati. Tendo a trovare me stesso preferendo questo metodo così anche se richiede più lavoro.

Raccomandazioni, commenti, idee alternative?

È stato utile?

Soluzione

Indipendentemente da ciò che Microsoft avrebbe potuto fare in passato, le attuali linee guida di progettazione API .NET scoraggiano la creazione di classi nidificate che sono visibili al di fuori le loro classi genitore. Vedere http://msdn.microsoft.com/en-us/library/ms229027 aspx per i dettagli.

Altri suggerimenti

Un'altra opzione è quella di nido classe di raccolta nella classe del bambino, e solo il nome è Collection. In questo modo, si ottiene sempre Child.Collection come nome.

public class Child
{
  public class Collection : ICollection<Child>
  {
  }
}

public class Parent
{
  private Child.Collection children;
}

Personalmente preferisco l'attuazione dei pari, promuove il riutilizzo del codice che non credo che l'attuazione nidificato fa. Se un'altra classe deve implementare un modo diverso di memorizzare una raccolta degli stessi elementi poi un'altra classe può essere facilmente implementato per quello scenario senza limitare il riutilizzo del codice.

Una configurazione annidata può anche portare alcuni sviluppatori a stretto paio loro codice alla classe padre.

Anch'io preferisco l'approccio peer. Non c'è davvero alcun motivo per il nido alla raccolta a meno che non si non lo usano al di fuori della sua classe principale (in questo caso, dovrebbe essere una classe privata annidata.)

Vorrei usare solo la disposizione annidata quando v'è una sola entità nel modello di dominio che può logicamente contenere le entità figlio.

Per esempio, se si ha una classe e una classe PieceOfMail invii postali collezione

  class PieceOfMail { } 
  class MailPieces: Collection<PieceOfMail> { }

allora la classe ShipingCompany, e la classe cassetta postale, e la classe PostOffice, e la classe MailRoute, e la classe MailManBag, potrebbero tutti avere una proprietà costitutiva digitato come invii postali, quindi mi piacerebbe utilizzare la tecnica "tra pari".

Ma OTOH, nello stesso dominio, se si ha una classe che rappresenta un tipo di PostageDiscount, e una classe collezione che rappresenta un insieme di sconti da applicare ad una spedizione, potrebbe essere il caso che solo la classe ShipmentTransaction poteva logicamente contenere una raccolta di tali sconti, quindi mi piacerebbe utilizzare la tecnica annidata ...

Avete veramente bisogno di un ChildEntityCollection? Perché non utilizzare un tipo di raccolta che viene fornita?

  //why bother?
//public class ChildEntityCollection : ICollection<ChildEntity>{}

public class ParentEntity
{
   //choose one
  private ChildEntity[] children;
  private List<ChildEntity> childrenInList;
  private HashSet<ChildEntity> childrenInHashSet;
  private Dictionary<int, ChildEntity> childrenInDictionary;
   // or if you want to make your own, make it generic
  private Balloon<ChildEntity> childrenInBalloon;
}
public class ChildEntity
{
}

Io in genere cerco di evitare di generare classi di raccolta specifici. A volte potrebbe essere necessario un classe speciale, ma in molti casi si può semplicemente utilizzare classi generiche come Collection<T> e ReadOnlyCollection<T> dallo spazio dei nomi System.Collection.ObjectModel. Questo permette di risparmiare un sacco di battitura. Tutte le vostre collezioni derivano da IEnumerable<T> ecc e sono facilmente integrabili con LINQ. A seconda delle esigenze si potrebbe anche esporre le vostre collezioni come ICollection<T> o un'altra interfaccia per la raccolta e poi lasciare che le classi con i requisiti specifici utilizzano altamente ottimizzati collezioni generiche.

public class ParentEntity {

  Collection<ChildEntity> children = new Collection<ChildEntity>();

  public Collection<ChildEntity> Children {
    get {
      return this.children;
    }
  }

}

Si può anche avvolgere un IList<T> in questo modo:

public class ParentEntity {

  // This collection can be modified inside the class.
  List<ChildEntity> children = new List<ChildEntity>();

  ReadOnlyCollection<ChildEntity> readonlyChildren;

  public ReadOnlyCollection<ChildEntity> Children {
    get {
      return this.readOnlyChildren
        ?? (this.readOnlyChildren =
              new ReadOnlyCollection<ChildEntity>(this.children));
    }
  }

}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top