3

我的一个项目中有以下类型的代码示例...

    [Obfuscation(Exclude = true)]
    [UsedImplicitly]
    public DelegateCommand<object> OpenXCommand { get; private set; }

我发现属性给代码添加了很多“噪音”——我也看到它违反了 DRY 原则,因为我可能在一个类中有几个这样的属性,所有属性都具有相同的属性装饰。

问:有什么方法可以设置代表子属性组合的属性?

理想情况下,我想要看起来像这样的东西..

    [MyStandardCommandAttribute]
    public DelegateCommand<object> OpenXCommand { get; private set; }

我之前没有实现自己的属性,所以我不确定这是否可能。有什么建议么?

4

2 回答 2

3

不,您的一个属性不能同时“是” ObfuscationUsedImplicitlyC# 中没有多重继承)。

查找例如UsedImplicitlyAttribute的代码无法知道MyStandardCommandAttribute应该表示的内容UsedImplicitlyAttribute(除非您使用所有这些属性控制所有代码)。

于 2013-02-12T01:26:57.367 回答
2

不幸的是,在 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 };
  }
}
于 2013-02-12T01:46:53.330 回答