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?

+3


source to share


2 answers


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).

+3


source


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

      

+2


source







All Articles