将当前对象类型传递给基础构造函数调用

时间:2010-02-18 09:53:10

标签: c# inheritance constructor types

如何抓取继承类的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)构造函数。

6 个答案:

答案 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 typebase 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)
    {
    }
}