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

时间:2013-03-15 01:27:52

标签: c# attributes base derived-class

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

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

  • 如何在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;
        }
    }
    

    所以我想我不能把属性放在基类中,而是将它放在派生类属性上,该属性使用/是根据受保护的基类属性实现的,但这很麻烦,它可以避免任何方便使用基类。

所以这是一个很好的方法,对吗?对?

如何在派生类的属性上重新定义属性,该属性继承自派生类中的基础 WITHOUT覆盖属性

1 个答案:

答案 0 :(得分:0)

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

不幸的是,你想做的事情远远超出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 ++模板样式一样接近。但我很高兴被证明是错的:)