Для моих целей мне нравится идея @T-moty. Несмотря на то, что я много лет использовал информацию о типе с саморегулированием, позже ссылаться на базовый класс будет труднее.
Например (используя пример @Rob Leclerc сверху):
public class ChildA: Parent<ChildA>
{
}
public class ChildB: Parent<ChildB>
{
}
Например, работа с этим шаблоном может быть сложной; как вернуть базовый класс из вызова функции?
public Parent<???> GetParent() {}
Или при приведении типов?
var c = (Parent<???>) GetSomeParent();
Поэтому я стараюсь избегать этого, когда могу, и использую, когда необходимо. Если необходимо, я бы посоветовал вам следовать этому шаблону:
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) {}
}
Теперь вы можете (более) легко работать с BaseClass
. Однако бывают случаи, как моя текущая ситуация, когда раскрытие производного класса из базового класса не требуется, и использование предложения @ M-moty может быть правильным подходом.
Однако использование кода @ M-moty работает только до тех пор, пока базовый класс не содержит конструкторов экземпляров в стеке вызовов. К сожалению, в моих базовых классах используются конструкторы экземпляров.
Поэтому вот мой метод расширения, который учитывает конструкторы экземпляра базового класса:
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;
}
}