3

是否可以将派生类的属性参数传递给其基类?

本质上,我正在尝试从派生类中设置属性的属性参数。

  • 如何在 C++ 中完成

    public class HasHistory<T, string name> {
        public HasHistory() {
            History=new History<T>();
        }
    
        // here's my attribute
        [BsonElement(name)]
        public History<T> History {
            get;
            protected set;
        }
    }
    

    但是,非类型模板参数在 C++ 中是合法的,但在 C# 中是非法的

  • C# 中的一个出乎意料的解决方法

    我意识到我可以将属性设为虚拟,并在派生类中添加属性。但是我会在构造函数中调用一个虚函数,虽然这可能有效,但这是不好的做法。

    我确实想进行该调用,因为我希望基类构造函数初始化成员;这实际上是基类的重点。

    public class HasHistory<T> {
        public HasHistory() {
            // this will be called before Derived is constructed
            // and so the vtbl will point to the property method
            // defined in this class.
            // We could probably get away with this, but it smells.
            History=new History<T>();
        }
    
        // here's my property, without an Attribute
        public virtual History<T> History {
            protected set;
            get;
        }
    }
    
    public class Derived: HasHistory<SomeType> {
        // crap! I made this virtual and repeated the declaration
        // just so I could add an attribute!
        [BsonElement("SomeTypeHistory")]
        public virtual HasHistory<SomeType> History {
            protected set;
            get;
        }
    }
    

    所以我想我不能把属性放在基类中,而是把它放在派生类属性上,该属性使用/是根据受保护的基类属性实现的,但这太麻烦了,它消除了使用基类所获得的任何便利班级。

所以有一个好方法可以做到这一点,对吧?正确的?

如何在不覆盖派生类中的属性的情况下重新定义从基类继承的派生类属性的属性?

4

1 回答 1

0

更新:该死,你已经考虑过了。我应该在发布之前更新:)

不幸的是,您想要做的远远超出了 C# 的属性机制的范围。泛型与模板不同,因此这种解决方法几乎可以做到。

大多数情况下,无论如何你都会在顶层定义一个属性,所以通常这不是问题。当这一个问题 - 显然在你的情况下 - 那么你必须使用丑陋的解决方法。

下面的原始答案...


如果我正确理解了该示例,则您希望根据派生类型中/由派生类型声明的某些值将属性应用于类成员。由于 C# 不支持泛型的非类型参数,因此您需要另一种方法来执行此操作。

您可能可以做的一件事是覆盖后代类中的属性,如下所示:

public class HasHistory<T>
{
    public HasHistory() 
    {
        History = new History<T>();
    }

    public virtual History<T> History { get; protected set; }
}

public class MyHistory<T> : HasHistory<T>
{
    public MyHistory()
        : base()
    {}

    [BSONElement("some name")]
    public override History<T> History 
    { 
        get
        {
            return base.History;
        }
        protected set
        {
            base.History = value;
        }
    }
}

使用该BsonElement属性的代码将使用派生实例的实际HasHistory<T>类型,因此它将查看在virtual链末尾定义的属性。鉴于上面的代码,如果我创建一个MyHistory<T>实例并将其传递给 BSON 序列化程序,它将找到附加到类中History属性的属性MyHistory<T>

但是,您可以在基本级别定义一个属性,并在必要时在派生类中覆盖它。不确定这对您的情况是否有用。

这是更多的工作,特别是因为您必须在每个派生类中执行此操作,但我认为在这种情况下,这与您将要获得的 C++ 模板样式一样接近。但是,我很高兴被证明是错误的:)

于 2013-03-15T05:21:13.113 回答