简体   繁体   中英

Is it possible to pass an attribute argument from a derived class to its base class?

Is it possible to pass an attribute argument from a derived class to its base class?

Essentially, I'm trying set a property's attribute's argument from the derived class.

  • How it could be done in 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; } } 

    However, non-type template arguments is legal in C++, but illegal in C# .

  • What an unexpected workaround in C#

    I realize I could make the property virtual, and add the attribute in the derived class. But then I'd be calling a virtual function in the constructor, and while that might work, it's poor practice.

    I do want to make that call because I want the base class constructor to initialize the member; that's in fact the whole point of the base class.

     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; } } 

    So I suppose I could not put the attribute in the base, and instead put it on a derived class property that uses/is implemented in terms of a protected base class property, but that's cumbersome enough that it obviates any convenience gained by using the base class.

So there's a good way to do this, right? Right?

How do I redefine an attribute on a property of derived class which inherits form the base WITHOUT overriding the property in the derived class?

Update: Darn, you already considered this. I should have updated before posting :)

Unfortunately what you want to do is well outside scope for C#'s attribute mechanism. Generics are different to templates, so this kind of workaround is about as good as it gets.

Mostly you're going to be defining an attribute at the top level anyway, so generally this isn't a problem. When it is a problem - as apparently in your case - then you have to use the ugly workarounds.

Original answer below...


If I understand the example correctly, you're wanting to apply an attribute to a class member based on some value declared in/by the derived type. Since C# doesn't support non-type parameters for Generics you need another way to do this.

One thing you might be able to do is override the property within the descendant class like this:

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;
        }
    }
}

The code that uses the BsonElement attribute will be working with the actual type of the derived HasHistory<T> instance, so it will be looking at the attributes defined at the end of the virtual chain. Given the code above, if I create a MyHistory<T> instance and pass it to the BSON serializer it will find the attribute attached to the History property within the MyHistory<T> class.

You can however define an attribute at the base level and override it in the derived classes where necessary. Not sure if this is going to be useful in your case.

It's more work, especially since you have to do this in each derived class, but I think this is as close as you're going to get to the C++ Template style in this case. I'd be happy to be proved wrong however :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM