tags:

views:

107

answers:

4
public class MyWebControl {

    [ExternallyVisible]
    public string StyleString {get;set;}

}

public class SmarterWebControl : MyWebControl {

    [ExternallyVisible]
    public string CssName{get;set;}

    new public string StyleString {get;set;} //Doesn't work

}

Is it possible to remove the attribute in the subclass? I do want the attribute to get inherited by other subclasses, just not this one.

Edit: Whoops, looks like I forgot to compile or something because the code as posted above does, in fact, work!

+4  A: 

This is exactly why framework attribures that can be "overriden", take a boolean parameter which (on the face of it) seems pointless. Take BrowsableAttribute for example; the boolean parameter would seem to be obsolete judging by the name, but take this example:

class SomeComponent
{
  [Browsable(true)]
  public virtual string SomeInfo{get;set;}
}

class SomeOtherComponent : SomeComponent
{
  [Browsable(false)]  // this property should not be browsable any more
  public override string SomeInfo{get;set;}
}

so, to answer your question, you could make your ExternallyVisible attribute take a boolean parameter, to indicate whether it is actually externally visible, and when you inherit you can change to false - just like BrowsableAttribute.

Jamiec
Hey, you stole my answer! +1
Chris Shouts
ach you stole my answer too!!!
John Nicholas
+2  A: 

You could inherit off the attribute and add a property that controls whether the attrbiute code fires or not.

then you can override the attributes behaviour on the inherited class?

so you would use (if you added a parameter to the constructor)

[ExternallyVisible(false)]

[ExternallyVisible(Enabled = false)]

i fyou used a property of enabled in the atrtibute class

John Nicholas
+2  A: 

I don't understand what the trouble is. Your posted code does the expected thing (at least, what it appears you expect it to do) in my test: that is, the StyleString property does not have the ExternallyVisible attribute. Here's my test code:

[AttributeUsage(AttributeTargets.Property)]
public class ExternallyVisible : Attribute
{
}

public class MyWebControl
{
    [ExternallyVisible]
    public string StyleString { get; set; }
}

public class SmarterWebControl : MyWebControl
{

    [ExternallyVisible]
    public string CssName { get; set; }

    new public string StyleString { get; set; } //Doesn't work

}

class Program
{
    static void Main()
    {
        MyWebControl myctrl = new MyWebControl();
        SmarterWebControl smartctrl = new SmarterWebControl();

        MemberInfo info = typeof(SmarterWebControl);
        PropertyInfo[] props = (typeof(SmarterWebControl)).GetProperties();
        Console.WriteLine("{0} properties", props.Length);

        foreach (var prop in props)
        {
            Console.WriteLine(prop.Name);
            foreach (var attr in prop.GetCustomAttributes(true))
            {
                Console.WriteLine("  " + attr);
            }
        }

        Console.ReadLine();
    }

}

In .NET 4.0, I get this output:

2 properties
CssName
  sotesto.ExternallyVisible
StyleString

In other words, the attribute is not applied to the StyleString property.

Jim Mischel
Beat me to it. :)
Chris Martin
+3  A: 

It works for me.

Test code:

    public static void Main()
{
    var attribute = GetAttribute(typeof (MyWebControl), "StyleString", false);
    Debug.Assert(attribute != null);

    attribute = GetAttribute(typeof(SmarterWebControl), "StyleString", false);
    Debug.Assert(attribute == null);

    attribute = GetAttribute(typeof(SmarterWebControl), "StyleString", true);
    Debug.Assert(attribute == null);
}

private static ExternallyVisibleAttribute GetAttribute(Type type, string propertyName, bool inherit)
{
    PropertyInfo property = type.GetProperties().Where(p=>p.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

    var list = property.GetCustomAttributes(typeof(ExternallyVisibleAttribute), inherit).Select(o => (ExternallyVisibleAttribute)o);

    return list.FirstOrDefault();
}
Chris Martin
Your reflection code is more succinct. Good job.
Jim Mischel