Para mis propósitos, me gusta la idea de @ T-moty. Aunque he usado información de "tipo de autorreferencia" durante años, hacer referencia a la clase base es más difícil de hacer más adelante.
Por ejemplo (usando el ejemplo de @Rob Leclerc de arriba):
public class ChildA: Parent<ChildA>
{
}
public class ChildB: Parent<ChildB>
{
}
Trabajar con este patrón puede ser un desafío, por ejemplo; ¿Cómo devuelve la clase base de una llamada a función?
public Parent<???> GetParent() {}
¿O cuando escribe casting?
var c = (Parent<???>) GetSomeParent();
Entonces, trato de evitarlo cuando puedo y lo uso cuando debo. Si es necesario, le sugiero que siga este patrón:
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) {}
}
Ahora puede trabajar (más) fácilmente con BaseClass
. Sin embargo, hay momentos, como mi situación actual, en los que no es necesario exponer la clase derivada, desde dentro de la clase base, y usar la sugerencia de @ M-moty podría ser el enfoque correcto.
Sin embargo, usar el código de @ M-moty solo funciona siempre que la clase base no contenga ningún constructor de instancia en la pila de llamadas. Desafortunadamente, mis clases base usan constructores de instancias.
Por lo tanto, aquí está mi método de extensión que tiene en cuenta los constructores de 'instancia' de la clase 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;
}
}