如何抓取继承类的Type
并将其传递给同样继承的类的基础构造函数?请参阅下面的代码示例:
// VeryBaseClass is in an external assembly
public abstract class VeryBaseClass
{
public VeryBaseClass(string className, MyObject myObject)
{
}
}
// BaseClass and InheritedClass are in my assembly
public abstract class BaseClass : VeryBaseClass
{
public BaseClass(MyObject myObject) :
base(this.GetType().Name, myObject) // can't reference "this" (Type expected)
{
}
}
public class InheritedClass : BaseClass
{
public InheritedClass(MyObject myObject)
{
}
}
行base(typeof(this).Name, myObject)
不起作用,因为我还不能引用this
,因为该对象尚未完成构建,因此不存在。
是否可以抓取当前构建对象的Type
?
编辑:
将示例更正为orsogufo suggested,但仍然无效,因为this
未定义。
编辑2:
为了澄清,我想最终将"InheritedClass"
传递给VeryBaseClass(string className, MyObject myObject)
构造函数。
答案 0 :(得分:18)
public abstract class VeryBaseClass
{
public VeryBaseClass(string className, MyObject myObject)
{
this.ClassName = className;
}
public string ClassName{ get; set; }
}
public abstract class BaseClass<T> : VeryBaseClass
{
public BaseClass(MyObject myObject)
: base(typeof(T).Name, myObject)
{
}
}
public class InheritedClass : BaseClass<InheritedClass>
{
public InheritedClass(MyObject myObject)
: base(myObject)
{
}
}
答案 1 :(得分:6)
我之前在Google Wave Robot .NET API中有过完全相同的痛苦,我想让构造函数根据属性传递一些值。您可以在derived type和base type的代码中查看我的解决方案。基本上我将一个委托传递给基础构造函数,然后调用该委托将“this”传递给委托。所以在你的情况下你会有:
public VeryBaseClass(Func<VeryBaseClass, string> classNameProvider)
{
this.name = classNameProvider(this);
}
和
public BaseClass() : base(FindClassName)
{
}
private static string FindClassName(VeryBaseClass @this)
{
return @this.GetType().Name;
}
这真的很难看,但它确实有用。
编辑:只有在您可以更改基类构造函数时,此方法才有效;如果你不能,我不确定它实际上是否可行:(
答案 2 :(得分:3)
GetType()。名称不起作用吗?
答案 3 :(得分:3)
可能的解决方案:
class VeryBase {
public VeryBase(string name) {
Console.WriteLine(name);
}
}
class Base<T> : VeryBase where T : Base<T> {
protected Base()
: base(typeof(T).Name) {
}
}
class Derived : Base<Derived> {
public Derived() {
}
}
class Program {
public static void Main(params string[] args) {
Derived d = new Derived();
}
}
答案 4 :(得分:3)
如果在运行时确定继承类的类型的能力比性能更重要,那么可以查看StackTrace以查看构造函数的调用位置。在此示例中调用GetInheritedClassName时,您可能需要编写更多假设代码:
public abstract class BaseClass : VeryBaseClass
{
private static string GetInheritedClassName
{
get
{
// Get the current Stack
StackTrace currentStack = new StackTrace();
MethodBase method = currentStack.GetFrame(1).GetMethod();
// 1st frame should be the constructor calling
if (method.Name != ".ctor")
return null;
method = currentStack.GetFrame(2).GetMethod();
// 2nd frame should be the constructor of the inherited class
if (method.Name != ".ctor")
return null;
// return the type of the inherited class
return method.ReflectedType.Name;
}
}
public BaseClass(MyObject myObject) :
base(GetInheritedClassName, myObject)
{
}
}
我想不出一个很好的方法来动态获取继承类的名称而不会影响性能。我意识到你想要避免的,但如果我需要调用具有这些要求的第三方程序集,我只需要每个类指定它自己的类型:
public abstract class BaseClass : VeryBaseClass
{
public BaseClass(string className, MyObject myObject) :
base(className, myObject)
{
}
}
public class InheritedClass : BaseClass
{
public InheritedClass(MyObject myObject) : base("InheritedClass", myObject)
{
}
}
答案 5 :(得分:0)
另一种选择......
// VeryBaseClass is in an external assembly
public abstract class VeryBaseClass
{
public VeryBaseClass(string className)
{
Console.WriteLine(className);
}
}
// BaseClass and InheritedClass are in my assembly
public abstract class BaseClass : VeryBaseClass
{
public BaseClass(string className)
:
base(className)
{
}
}
public class InheritedClass : BaseClass
{
public InheritedClass()
: base(typeof(InheritedClass).Name)
{
}
}