Untuk tujuan saya, saya suka ide @ T-moty. Meskipun saya telah menggunakan informasi "tipe referensi sendiri" selama bertahun-tahun, merujuk kelas dasar lebih sulit dilakukan nanti.
Misalnya (menggunakan contoh @Rob Leclerc dari atas):
public class ChildA: Parent<ChildA>
{
}
public class ChildB: Parent<ChildB>
{
}
Bekerja dengan pola ini dapat menjadi tantangan, misalnya; bagaimana Anda mengembalikan kelas dasar dari pemanggilan fungsi?
public Parent<???> GetParent() {}
Atau saat mengetik casting?
var c = (Parent<???>) GetSomeParent();
Jadi, saya mencoba menghindarinya saat saya bisa, dan menggunakannya saat harus. Jika Anda harus, saya sarankan Anda mengikuti pola ini:
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) {}
}
Sekarang Anda dapat (lebih) mudah bekerja dengan file BaseClass
. Namun, ada kalanya, seperti situasi saya saat ini, di mana mengekspos kelas turunan, dari dalam kelas dasar, tidak diperlukan dan menggunakan saran @ M-moty mungkin merupakan pendekatan yang tepat.
Namun, penggunaan kode @ M-moty hanya berfungsi selama kelas dasar tidak berisi konstruktor instance apa pun dalam tumpukan panggilan. Sayangnya kelas dasar saya memang menggunakan konstruktor instance.
Oleh karena itu, inilah metode ekstensi saya yang memperhitungkan konstruktor 'instance' kelas dasar:
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;
}
}