Pour mes besoins, j'aime l'idée de @ T-moty. Même si j'utilise des informations de "type d'auto-référencement" depuis des années, il est plus difficile de référencer la classe de base plus tard.
Par exemple (en utilisant l'exemple @Rob Leclerc ci-dessus):
public class ChildA: Parent<ChildA>
{
}
public class ChildB: Parent<ChildB>
{
}
Travailler avec ce modèle peut être difficile, par exemple; comment renvoyez-vous la classe de base à partir d'un appel de fonction?
public Parent<???> GetParent() {}
Ou lors du casting de type?
var c = (Parent<???>) GetSomeParent();
Alors, j'essaye de l'éviter quand je le peux et de l'utiliser quand je le dois. Si vous le devez, je vous suggère de suivre ce modèle:
class BaseClass
{
// All non-derived class methods goes here...
// For example:
public int Id { get; private set; }
public string Name { get; private set; }
public void Run() {}
}
class BaseClass<TSelfReferenceType> : BaseClass
{
// All derived class methods goes here...
// For example:
public TSelfReferenceType Foo() {}
public void Bar(TSelfRefenceType obj) {}
}
Vous pouvez désormais (plus) facilement travailler avec le BaseClass
. Cependant, il y a des moments, comme ma situation actuelle, où exposer la classe dérivée, à partir de la classe de base, n'est pas nécessaire et utiliser la suggestion de @ M-moty pourrait être la bonne approche.
Cependant, l'utilisation du code de @ M-moty ne fonctionne que tant que la classe de base ne contient aucun constructeur d'instance dans la pile d'appels. Malheureusement, mes classes de base utilisent des constructeurs d'instances.
Par conséquent, voici ma méthode d'extension qui prend en compte les constructeurs d'instance de la classe de base:
public static class TypeExtensions
{
public static Type GetDrivedType(this Type type, int maxSearchDepth = 10)
{
if (maxSearchDepth < 0)
throw new ArgumentOutOfRangeException(nameof(maxSearchDepth), "Must be greater than 0.");
const int skipFrames = 2; // Skip the call to self, skip the call to the static Ctor.
var stack = new StackTrace();
var maxCount = Math.Min(maxSearchDepth + skipFrames + 1, stack.FrameCount);
var frame = skipFrames;
// Skip all the base class 'instance' ctor calls.
//
while (frame < maxCount)
{
var method = stack.GetFrame(frame).GetMethod();
var declaringType = method.DeclaringType;
if (type.IsAssignableFrom(declaringType))
return declaringType;
frame++;
}
return null;
}
}