出于我的目的,我喜欢@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;
}
}