不幸的是,在 C# 中没有办法做到这一点。
但是,如果您控制读取这些属性的位置(通过反射),则可以按照约定进行。
例如,您可以有一个标记界面,该界面将使用它代理的属性“注释”您的属性(听起来像meta-attribute):
public interface AttributeProxy<T>
where T : Attribute {}
public class MyStandardCommandAttribute :
Attribute,
AttributeProxy<ObfuscationAttribute>,
AttributeProxy<UsedImplicitlyAttribute> {}
(当然,你也必须匹配正确AttributeUsage
的s。你不能像这样在代理属性上设置属性。)
现在,您可以更进一步,使用 IL 操作库(如 Mono.Cecil)在编译后步骤中实际适当地传输属性。在这种情况下,即使您不考虑这些属性,它也会起作用。
更新:仍然在 reflect-your-own-attributes 场景中,您可以使用以下代码获取代理属性,甚至设置属性值:
public interface IAttributeProxy {
Attribute[] GetProxiedAttributes();
}
public class MyStandardCommandAttribute : Attribute, IAttributeProxy {
public Attribute[] GetProxiedAttributes() {
return new Attribute[] {
new ObfuscationAttribute { Exclude = true },
new UsedImplicitlyAttribute()
};
}
}
在反射代码上使用此扩展方法:
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 };
}
}