2016-01-13 106 views
0

如何讓一個屬性中的屬性知道另一個屬性的存在?如何讓屬性'A'中的屬性知道屬性'B'的存在?

可以說我有這個類,像這樣,許多人:

public class MyClass 
{ 
    [CheckDirty] //a custom attribute (that it is empty for now) 
    public int A { get; set; } 
    public int B { get; set; } 

    public string Description { get; set; } 
    public string Info { get; set; } 
} 

某處在我們的程序中,如果我們希望看到一個對象是否改變了對任何CheckDirty屬性值,例如可以說它從DB diferent,MyPropertyUtils.GetPropertiesIfDirty()做到這一點,讓我們改變propertys的陣列,與該屬性的任何屬性:

PropertyInfo[] MyPropertyUtils.GetPropertiesIfDirty(SomeBaseObject ObjectFromDB, SomeBaseObject NewValues); 

完美。

因此,可以說A已更改,在這種情況下Info包含我們需要的一些信息(在另一個類中可能是任何其他屬性)。如果我們想'A'我們只是做property.GetValue(NewValues, null);

但是我們不想'A的價值,我們想'A'或CheckDirty告訴我們在哪裏閱讀我們想要的一些數據。我如何告訴我的屬性CheckDirty從哪裏獲取值?

我在考慮給出CheckDirty的表達式,但是Attribute的參數「必須是常量表達式,屬性參數類型的typeof表達式或數組創建表達式」(這就是VS所說的)。 所以我決定,「好吧,讓我們給它一個字符串與屬性的名稱」,所以我嘗試失敗:

(這是我們需要處理的所有代碼,其餘的只是給某種背景例子)

public class CheckDirty : Attribute 
{ 
    public String targetPropertyName; 

    public CheckDirty(String targetPropertyName) 
    { 
     this.targetPropertyName = targetPropertyName; 
    } 
} 

public class MyClass 
{ 
    //Code fails on this line 
    [CheckDirty(BoundPropertyNames.Info)] 
    public int Id { get; set; } 

    public string Info { get; set; } 

    public static class BoundPropertyNames 
    { 
     public static readonly string Info = ((MemberExpression) 
                 ((Expression<Func<MyClass, string>>) 
                  (m => m.Info) 
                 ).Body 
                ).Member.Name; 
    } 
} 

這是錯誤我得到:

An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type 

我們不想通過proprety的名稱作爲String saing [CheckDirty("Info")]因爲這樣,如果有人在將來改變類,並在具體的適當ty的名字,編譯時就不會拋出錯誤,只會在運行時發生錯誤,當編輯該字段時會發生。或者,也許它不會做任何事情,因爲它找不到該財產。

任何想法如何不使用強類型字符串作爲屬性名稱?

+2

你可以使用Visual Studio 2015嗎?如果是這樣,請使用[nameof運算符。](https://msdn.microsoft.com/en-us/library/dn986596.aspx) –

+0

我正在使用VS 2013.不是我的電腦,無法安裝的東西。 –

+0

將一個屬性附加到另一個屬性,並使用唯一的字符串進行鏈接,除了鏈接這兩個屬性之外,它沒有任何用途。您必須在屬性中使用常量表達式,所以除了您稱之爲不能使用的新'nameof'運算符之外,沒有辦法執行此操作。 –

回答

1

你可以使用這樣的事情,首先聲明,將通過每一個類實現一個接口,需要髒檢查:

interface IDirtyCheckPropertiesProvider { 
    string GetPropertyName(string dirtyProperty); 
} 

然後實現它這樣

class DataEntity : IDirtyCheckPropertiesProvider { 
    [CheckDirty] 
    public int Id { get; set; } 

    public string Info { get; set; } 

    string GetPropertyName(string dirtyProperty) { 
     if (GetPropertyNameFromExpression(x => Id) == dirtyProperty) 
      return GetPropertyNameFromExpression(x => Info); 

     return null; 
    } 
} 

在類,將負責處理髒檢查,您必須使用此界面來獲取目標屬性名稱。 有一些樣板太多,可能會通過使用Reflection API進一步刪除。

另一方面,使用屬性名稱字符串看起來像更簡單的解決方案。如果您使用像Resharper這樣的工具 - 使用字符串是一個可行的選項 - 當您更改屬性名稱時,Resharper會自動重構字符串。 也很長一段時間string'ed屬性名稱用於實現WPF INotifyPropertyChanged。

由於意見建議nameof是VS2015中的最佳選擇。

+0

謝謝。把它適應我的情況後,它就像一個魅力。 –