Create attribute to represent multiple auxiliary attributes in c #
I have the following type of code for one of my projects ...
[Obfuscation(Exclude = true)]
[UsedImplicitly]
public DelegateCommand<object> OpenXCommand { get; private set; }
I find that attributes add a lot of "noise" to the code - I also see this in a way that violates the DRY principle, as I can have multiple properties like this in the same class, all with the same attribute decoration.
Q: Is it possible to somehow customize an attribute that will be a combination of auxiliary attributes?
Ideally I would like something similar to this.
[MyStandardCommandAttribute]
public DelegateCommand<object> OpenXCommand { get; private set; }
I haven't implemented my own attributes previously, so I'm not sure if this is possible. Any suggestions?
source to share
Not. Your one attribute can not be "to be" Obfuscation
and UsedImplicitly
at the same time (no multiple inheritance in C #).
Search for code, eg. UsedImplicitlyAttribute
doesn't know what it MyStandardCommandAttribute
should represent UsedImplicitlyAttribute
(unless you are in control of all the code using all these attributes).
source to share
Unfortunately, there is no way to do this in C #.
But if you control the places that read these attributes (with reflection), you can do it by convention.
For example, you might have a marker interface that "annotates" your attribute with the attributes it proxies (sounds like a meta attribute):
public interface AttributeProxy<T>
where T : Attribute {}
public class MyStandardCommandAttribute :
Attribute,
AttributeProxy<ObfuscationAttribute>,
AttributeProxy<UsedImplicitlyAttribute> {}
(Of course, you must also match the right AttributeUsage
s. And you cannot set properties on proxy attributes like this.)
You can now take it a step further and use an IL manipulation library like Mono.Cecil to actually wrap the attributes in a later compilation step. In this case, it will work even if you don't think about these attributes.
Update : Still in a scenario with reflection of your own attribute, you can use the below code to get the proxied attributes, even setting property values:
public interface IAttributeProxy {
Attribute[] GetProxiedAttributes();
}
public class MyStandardCommandAttribute : Attribute, IAttributeProxy {
public Attribute[] GetProxiedAttributes() {
return new Attribute[] {
new ObfuscationAttribute { Exclude = true },
new UsedImplicitlyAttribute()
};
}
}
Use this extension method for reflection code:
public static object[] GetCustomAttributesWithProxied(this MemberInfo self, bool inherit) {
var attributes = self.GetCustomAttributes(inherit);
return attributes.SelectMany(ExpandProxies).ToArray();
}
private static object[] ExpandProxies(object attribute) {
if (attribute is IAttributeProxy) {
return ((IAttributeProxy)attribute).GetProxiedAttributes().
SelectMany(ExpandProxies).ToArray(); // don't create an endless loop with proxies!
}
else {
return new object[] { attribute };
}
}
source to share