There's a fine question on overriding inherited attributes of properties.
Suppose an attribute:
[AttributeUsage(AttributeTargets.All, Inherited = true)]
public class MyAttributeAttribute : Attribute
//...
public class ParentClass
{
[MyAttribute]
public String MyString;
}
public class ChildClass : ParentClass
{
new public String MyString; //Doesn't have MyAttribute
}
But what if MyAttribute is set to a class?
[MyAttribute]
public class ParentClass
public class ChildClass; //Don't want MyAttribute
Is there a way to make ChildClass not inherit the attribute?
Context: Purely theoretical. I want to make an attribute inheritable and want to know, if the case happens some day, if I can override it.
You could copy the BrowsableAttribute approach mentioned in one of the answers to the question you reference. You can make a constructor with a boolean that when set to false will denote that the attribute, although present, should not be handled. You can also add a parameterless constructor that set the property to true. This is the one that you will use most often unless you decide to override the attribute inherited from a base class.
[AttributeUsage(AttributeTargets.All, Inherited = true)]
public class MyAttributeAttribute : Attribute
{
public bool Enabled { get; private set; }
public MyAttributeAttribute()
:this(true)
{
}
public MyAttributeAttribute(bool enabled)
{
Enabled = enabled;
}
}
Then when you reflect on your types and look for the attribute, you can check on the Enabled property and only if it is true you actually use it.
Your example class hierarchy will then be:
[MyAttribute]
public class ParentClass
[MyAttribute(false)]
public class ChildClass; //Don't want MyAttribute
Related
I'm try to find a solution to realize decrypt/encrypt when access a class property by get/set.
I had researched something about C# custom attribute, but seemimgly it can't work, so I want to know whether it's impossible to change the class property by attribute.
[AttributeUsage(AttributeTargets.Property)]
public class MyAttribute : Attribute
{
// How to change the tragetClass.Name when access by get/set
}
public class TargetClass
{
[MyAttribute]
public string Name { get; set; }
}
In a class I have a property
protected abstract string test{ get; }
When I try to initialize it in a constructor. I get an error saying:
Property or indexer xxx cannot be assigned to. -- it is read-only.
Is there a way to allow some property to be
abstract
Read-only after initialization in ctor ?
You likely don't want an abstract property. You would only use that if you wanted to force the derived class to provide a custom implementation. In your case you simply want it to be set in the constructor and readonly.
public abstract class Base
{
protected string MyProperty { get; }
public Base(string myProperty)
{
MyProperty = myProperty;
}
}
public class Derived : Base
{
public Derived()
: base("DefaultValue")
{ }
}
So I have a base class and there a property that is set to be [Serializable].
In the derived class I would like to make that property [NonSerialized].
How can this be done?
This would be a violation of OOP. The base class has established the fact that this property is serializable. It must be possible to substitute any instance of a derived class for an instance of the base class. This means that every instance of the derived class must have that property serializable.
You cannot substitute a new attribute, but you can define a property called ShouldSerializePropertyName (where PropertyName is the name of your property) that always returns false. This should override the presence of the attribute on the property.
For example,
public class BaseClass
{
[Serialized]
public string MyProperty { get; set; }
}
public class ChildClass : BaseClass
{
public bool ShouldSerializeMyProperty { get { return false; } }
}
In a base class, I want to define an abstract get, but at that point, I don't care about the set. How can I define a setter in my child class?
I tried a few things, but I can't get it to work. For example I tried :
public class BaseClass
{
public abstract bool MyBool { get; }
}
public class ChildClass : BaseClass
{
public override bool MyBool { get; protected set;}
}
And :
public class BaseClass
{
public bool MyBool { abstract get; }
}
public class ChildClass : BaseClass
{
public bool MyBool { override get; protected set;}
}
I know I can workaround this by not using automatic properties in the child class and directly setting the underlying field instead of creating a setter, but I'm looking for something better.
Edit: I don't want to add an abstract setter in the BaseClass.
It may make more sense to use an interface rather than a base class. Then you simply have the classes that need to provide that property implement that interface.
For instance, you can create this interface:
public interface IBoolable {
bool MyBool { get; }
}
Then it is still valid to implement the interface like so:
public class BoolableItem : IBoolable {
public bool MyBool { get; protected set; }
}
Done this way, your code can safely assume anything that implements IBoolable has a property called MyBool that is at minimum read-only.
One solution is to make MyProperty not abstract but delegate its implementation to an abstract protected property that children must override:
public abstract class BaseClass
{
public bool MyBool { get { return MyBoolInternal; } }
protected abstract bool MyBoolInternal { get; set; }
}
public class ChildClass : BaseClass
{
protected override bool MyBoolInternal { get; set; }
}
You have to make up your mind what behavior you want: if it is defined as abstract then a deriving class MUST implement it.
So what you should do is this:
public abstract class BaseClass
{
public abstract string MyProperty { get; set; }
}
public class DerivedClass : BaseClass
{
public override string MyProperty
{
get { return "myValue"; }
set { /* do nothing, not applicable for this class */ }
}
}
Don't throw the NotImplementedException - that is not what you want, you simply want the setter to do nothing for some child classes.
To leave it ambiguous whether you want a setter in inherited classes would violate OOP principles--that is, if a class (abstract or not) has a public/protected setter (abstract or not), then all inheriting classes must also; if a class does not, then inheriting classes must not.
Another way to think about this is to consider properties such that read-only or read-write is part of the contract of the class. Since instances of inheriting classes must adhere to an "Is-a relationship" (the LSP), inheriting classes cannot "add a setter" where the main class didn't have one, because the fact that the main class had a property without as setter is part of the main class definition. In effect, since the main class cannot change the property in question via a setter, therefore all inheriting classes MUST guarantee the same behavior.
Consider using a protected backing field; then you can split this property into a read-only property and a separate setter method. Then, the main class can have the property only and the subclass can have a setter method that the main class doesn't know about. However, I'm not sure this would be a good design either.
Given the following, I would not expect the compiler to allow multiple attributes that are derived from the base attribute, given that is set to AllowMultiple=false. In fact it compiles without a problem - what am I missing here?
using System;
[AttributeUsage(AttributeTargets.Property,AllowMultiple=false,Inherited=true)]
abstract class BaseAttribute : Attribute { }
sealed class DerivedAttributeA : BaseAttribute { }
sealed class DerivedAttributeB : BaseAttribute { }
class Sample1
{
[DerivedAttributeA()]
[DerivedAttributeB()]
public string PropertyA{ get; set; } // allowed, concrete classes differ
[DerivedAttributeA()]
[DerivedAttributeA()]
public string PropertyB { get; set; } // not allowed, concrete classes the same, honours AllowMultiple=false on BaseAttribute
}
The problem is simply that the AllowMultiple check only compares attributes of the same actual type (i.e. the concrete type instantiated) - and is perhaps best used with sealed attributes for this reason.
It will, for example, enforce the following (as an illegal duplicate), inheriting this from BaseAttribute:
[DerivedAttributeB()]
[DerivedAttributeB()]
public string Name { get; set; }
In short, I don't think you can do what you want here... (enforce no more than one instance including subclasses of BaseAttribute per property).
A similar example of this problem would be:
[Description("abc")]
[I18NDescriptionAttribute("abc")]
public string Name { get; set; }
class I18NDescriptionAttribute : DescriptionAttribute {
public I18NDescriptionAttribute(string resxKey) : base(resxKey) { }
}
The intent above is to provide a [Description] from resx at runtime (fully supported by ComponentModel etc) - but it can't stop you also adding a [Description].