2013-02-12 113 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