2013-02-12 100 views
3

我有以下类型在我的项目之一代码示例...创建属性来表示在C#中的多个子属性

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

我发现的属性被加入了很多“噪音”的代码 - 我还以违反DRY原则的方式来看它,因为我可能在一个类中有这样的几个属性,所有这些都具有相同的属性修饰。

问:有没有什么办法可以设置一个属性来代表子属性的组合?

理想我想的东西,看起来像这样..

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

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

+1

你用什么来反映属性? – 2013-02-12 01:27:06

+0

顺便说一句,你可以将这两个属性合并成一行:'[Obfuscation(Exclude = true),UsedImplicitly]'。 – svick 2013-02-13 03:00:09

+0

@svick - thaks - 我没有意识到, – 2013-02-14 10:37:36

回答

3

不可以。您的一个属性不能同时为ObfuscationUsedImplicitly(在C#中没有多重继承)。

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

2

不幸的是,在C#中没有办法做到这一点。

但是,如果您控制读取这些属性的位置(带反射),则可以按照约定来执行

例如,你可以有一个标记接口,将“注解”与它所代理的属性的属性(听起来像一个元属性):

public interface AttributeProxy<T> 
    where T : Attribute {} 

public class MyStandardCommandAttribute : 
    Attribute, 
    AttributeProxy<ObfuscationAttribute>, 
    AttributeProxy<UsedImplicitlyAttribute> {} 

(当然,你也有以匹配右边的AttributeUsage s,而且你不能像这样在代理属性上设置属性。)

现在,你可以更进一步,使用IL操作库(如Mono.Cecil)来实际传输在编译后的步骤中适当的属性。在这种情况下,即使它没有反映这些属性,它也会起作用。

更新:依然在反映你自己的属性的情况下,你可以使用下面的代码去代理的属性,甚至设置属性值:

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

谢谢你的建议Jordao – 2013-02-19 13:26:14