Bei einem gegebenen Klassentyp muss ich seine vollständige Hierarchie ermitteln, einschließlich der Basis- und abgeleiteten Klassen . Die einzige Anforderung, die einen Schraubenschlüssel ins Wanken bringt, ist, dass offene generische Typen in beide Richtungen in die Ergebnismenge einbezogen werden müssen.
Gegeben ist eine Menge von Klassen wie Klasse A , B: A, C: B und D: C, E: D, das Ergebnis der Hypothese DiscoverTypeTree(typeof(C)) ist [
Code: Select all
A
Code: Select all
B
Code: Select all
D
Ich stecke nicht fest, weil ich anscheinend keine Möglichkeit finde, die offenen generischen Typen konsistent einzubeziehen in der Ausgabe zusammen mit ihren konkreten Versionen. In verschiedenen Iterationen konnte ich entweder nicht alle abgeleiteten Typen erkennen, wenn offene Generika involviert waren, oder ich habe nur die konkreten Typen einbezogen und die offenen Generika im Ergebnis übersprungen, oder es gab andere Probleme mit fehlenden Typen. Ich stecke jetzt mit dem Problem fest, dass nur die konkreten Typen einbezogen werden und die offenen Generika im Ergebnis übersprungen werden. Für das obige Beispiel ist das falsche Ergebnis also das von [
Code: Select all
A
Code: Select all
D
Der Code (die Sprachversion ist 13 und ich ziele auf .NET 8; dies ist als lokale Funktion geschrieben):
Code: Select all
var hierarchies = new Dictionary();
var derivedTypes = new Dictionary();
void discoverHierarchy()
where T : class {
void _discover(Type type) {
if (!hierarchies.ContainsKey(type)) {
var hierarchy = new LinkedList();
hierarchies.Add(type, hierarchy);
var t2 = type;
do {
_ = hierarchy.AddFirst(t2);
_discover(t2);
t2 = t2.BaseType;
}
while (t2 is not null && t2 != typeof(object));
var derived = new List();
var def = type.IsGenericTypeDefinition ? type : null;
if (def is not null && def != type) {
_discover(def);
}
foreach (var t in assemblyTypes) // Cached output of `assembly.GetTypes()`.
{
if (t.IsSubclassOf(type)) {
derived.Add(t);
_discover(t);
} else {
var t3 = t;
var list3 = new List();
do {
list3.Add(t3);
if (t3.BaseType?.IsGenericType is true && t3.BaseType.GetGenericTypeDefinition() == def) {
derived.AddRange(list3);
foreach (var _t3 in list3) {
_discover(_t3);
}
break;
} else {
t3 = t3.BaseType;
}
}
while (t3 is not null);
}
}
_ = derivedTypes.TryAdd(type, []);
derivedTypes[type].AddRange(derived);
}
};
var type = typeof(T);
_discover(type);
}