Ich habe eine Reihe von benutzerdefinierten Sammlung Klassen. Jedes dient dazu, eine Sammlung verschiedener benutzerdefinierter Typen bereitzustellen - einen benutzerdefinierten Typ für eine benutzerdefinierte Sammlung. Die benutzerdefinierten Sammlungen erben List<T>
[wobei T in diesem Fall der spezifische benutzerdefinierte Typ und nicht ein generischer Typ ist] und bieten einige zusätzliche Funktionen.Klassen mit praktisch gemeinsamen Code
Ich habe zuvor die benutzerdefinierten Sammlungen entfernt und hatte benutzerdefinierte Methoden an anderer Stelle, aber ich fand, wie ich den Code erweiterte, dass ich die Sammlungen mit ihren eigenen Methoden brauchte.
Alles funktioniert, alles ist glücklich. Aber es irritiert mich, weil ich weiß, dass ich es nicht richtig mache. Das Problem ist, dass jede Klasse so ziemlich den gleichen Code verwendet und nur den Typ und einen Parameter variiert, so dass ich denke, dass sie als abstrakte Klasse oder als generische oder Erweiterung zu List implementiert werden kann, oder ... aber ich bin Ich verstehe nicht genug von den Unterschieden oder wie ich das machen kann, um herauszufinden, was ich brauche.
Hier sind zwei meiner mehreren Sammlungen, so dass Sie auf die Idee:
// JourneyPatterns
public class JourneyPatterns : List<JourneyPattern>
{
private Dictionary<string, JourneyPattern> jpHashes; // This is a hash table for quick lookup of a JP based on its values
/* Add a journey pattern to the JourneyPatterns collection. Three methods for adding:
1. "Insert Before" (=at) a particular point in the list. This is the method used by all three methods.
2. "Insert After" a particular point in the list. This is "before" shifted by 1 e.g. "after 6" is "before 7"
3. "Append" to the end of the list. This is "before" with a value equal to the list count, and is the same as inherited "Add", but with checks
*/
public JourneyPattern InsertBefore(JourneyPattern JP, int before)
{
// check for a pre-existing JP with the same parameters (ignore ID). Do this by constructing a "key" based on the values to check against
// and looking it up in the private hash dictionary
JourneyPattern existingJP;
if (jpHashes.TryGetValue(JP.hash, out existingJP)) { return existingJP; }
else
{
// construct a new ID for this JP
if (string.IsNullOrWhiteSpace(JP.id)) JP.id = "JP_" + (Count + 1).ToString();
// next check that the ID specified isn't already being used by a different JPS
if (Exists(a => a.id == JP.id)) JP.id = "JP_" + (Count + 1).ToString();
// now do the add/insert
if (before < 0) { Insert(0, JP); } else if (before >= Count) { Add(JP); } else { Insert(before, JP); }
// finally add to the hash table for fast compare/lookup
jpHashes.Add(JP.hash, JP);
return JP;
}
}
public JourneyPattern InsertAfter(JourneyPattern JP, int after) { return InsertBefore(JP, after + 1); }
public JourneyPattern Append(JourneyPattern JP) { return InsertBefore(JP, Count); }
}
// JourneyPatternSections
public class JourneyPatternSections : List<JourneyPatternSection>
{
private Dictionary<string, JourneyPatternSection> jpsHashes; // This is a hash table for quick lookup of a JPS based on its values
/* Add a journey pattern section to the journeyPatternSections collection. Three methods for adding:
1. "Insert Before" (=at) a particular point in the list. This is the method used by all three methods.
2. "Insert After" a particular point in the list. This is "before" shifted by 1 e.g. "after 6" is "before 7"
3. "Append" to the end of the list. This is "before" with a value equal to the list count, and is the same as inherited "Add", but with checks
*/
public JourneyPatternSection InsertBefore(JourneyPatternSection JPS, int before)
{
// check for a pre-existing JPS with the same parameters (ignore ID). Do this by constructing a "key" based on the values to check against
// and looking it up in the private hash dictionary
JourneyPatternSection existingJPS;
if (jpsHashes.TryGetValue(JPS.hash, out existingJPS)) { return existingJPS; }
else
{
// construct a new ID for this JPS
if (string.IsNullOrWhiteSpace(JPS.id)) JPS.id = "JPS_" + (Count + 1).ToString();
// next check that the ID specified isn't already being used by a different JPS
if (Exists(a => a.id == JPS.id)) JPS.id = "JPS_" + (Count + 1).ToString();
// now do the add/insert
if (before < 0) { Insert(0, JPS); } else if (before >= Count) { Add(JPS); } else { Insert(before, JPS); }
// finally add to the hash table for fast compare/lookup
jpsHashes.Add(JPS.hash, JPS);
return JPS;
}
}
public JourneyPatternSection InsertAfter(JourneyPatternSection JPS, int after) { return InsertBefore(JPS, after + 1); }
public JourneyPatternSection Append(JourneyPatternSection JPS) { return InsertBefore(JPS, Count); }
}
Wie Sie sehen können, was unterschiedlich ist, ist die Art (JourneyPattern oder JourneyPatternSection) und das Präfix, das ich bin Verwenden für die "ID" -Eigenschaft des Typs ("JP_" oder "JPS_"). Alles andere ist üblich, da die Methode zur Bestimmung der "Eindeutigkeit" (die Eigenschaft "Hash") Teil des benutzerdefinierten Typs ist.
Einige meiner benutzerdefinierten Sammlungen erfordern mehr involvierte und andere Implementierungen dieser Methoden, was in Ordnung ist, aber das ist die häufigste und ich habe es bisher etwa 6 Mal implementiert, was a) sinnlos und b) schwieriger scheint aufrecht erhalten.
Ihre Gedanken und Hilfe geschätzt!
Machen Sie Ihre Klassen implementieren eine Schnittstelle, die enthalten s Eigenschaften "ID" und "Hash" und Typ auf diese Schnittstelle (Klasse YourCollection: Liste wo T: IYourInterface). –
Evk
OK, ich kann sehen, wie das funktionieren könnte. Vermutlich würde ich auch die benutzerdefinierten Typen benötigen, um auch eine andere Eigenschaft in der Schnittstelle zu implementieren, z. "id_pfx", so dass die Sammlung wusste, welches Präfix für die ID – StuartR143
Yes verwendet werden soll, oder lassen Sie die Sammlung selbst Präfix speichern, wie die Antwort unten suggeriert. – Evk