2013-01-12 113 views
2

我有一系列'代碼',我想引用我的課程中的屬性。但是,當我設置字典的值時,屬性不會更新。下面C#屬性字典#

public Foo() { 
    this.CodeMap = new Dictionary<string, object>(); 
    this.CodeMap.Add("stat", this.Status); 
    this.CodeMap.Add("ver", this.Version); 
} 

public int Status { get; set; } 

public int Version { get; set; } 

一個例子,並且調用代碼

foo.CodeMap["stat"] = 27; 
/* foo.Status is not set to 27 */ 

有沒有辦法在.NET中做到這一點。我相信發生錯誤的原因是字典值不是一個ref值,但我不確定最好的方法來做到這一點。我看到了https://stackoverflow.com/a/10350484/450745,但這與我想要的相反。

+0

當有人寫'foo.CodeMap [「stat」] =「blah」;'?時,你會發生什麼? –

+0

我希望屬性Status可以像指針一樣更新。假設你傳遞了一個int而不是一個字符串。 – Michael

+0

您的示例缺少很多細節,假設您正在複製某些類的主體,並且foo變量是該類的一個實例,則您想要執行的操作是框和取消箱的狀態和版本。閱讀:http://msdn.microsoft.com/en-us/library/yz2be5wk.aspx –

回答

1

您的代碼無法正常工作,因爲您將密鑰「stat」添加到Dictionary,並使用狀態在分配時所做的任何值。稍後更新該密鑰的值時,它不會自動更新您的財產。您正在將時間爲的物業的價值添加到Dictionary,但不是物業本身。

你想要做的是不可能使用標準Dictionary。你有幾個選項看起來並不可怕。

可觀察字典

看到這個blog poststackoverflow thread

總的想法是編寫一個繼承自IDictionary<TKey, TValue>,INotifyCollectionChangedINotifyPropertyChanged的類。

這會給你一些鉤子,你可以編寫事件處理程序,理論上可以讓你更新一些屬性或任何你想做的事情。

重構代碼

如果你不喜歡上面的,那麼你可以稍稍重構你的代碼。

考慮一下:

public class Foo 
{ 
    public Dictionary<string, object> CodeMap; 

    public int Status 
    { 
     get 
     { 
      int status; 
      if (int.TryParse(CodeMap["stat"].ToString(), out status)) 
      { 
       return status; 
      } 
      else 
      { 
       throw new Exception("Status has a non-numeric value"); 
      } 
     } 
     set 
     { 
      CodeMap["stat"] = value; 
     } 
    } 

    public Foo() 
    { 
     CodeMap = new Dictionary<string, object>(); 
    } 
} 

然後,你可以讓相同的呼叫:

Foo foo = new Foo(); 
foo.CodeMap["stat"] = 27; 

Console.WriteLine(foo.Status.ToString()); // prints 27 

希望這是相當顯而易見的,爲什麼這個工程。現在該物業實際上引用了Dictionary。請注意,您不能像以前一樣添加初始值,因爲當獲取方嘗試訪問該密鑰時,您會得到一個KeyNotFoundException。然而,我認爲這是一個非常小的缺點。

+0

謝謝。我將使用一個可觀察的字典。 – Michael

1

我相信,因爲字典值不是參考值時出現錯誤,

沒有那是因爲你沒有設置foo.Statusfoo.CodeMapfoo.Status是不同的。

如果你想同步這些值,你應該手動完成。您可以繼承IDictionary<TKey,TValue>並覆蓋Add方法。

void Add(TKey key, TValue value) 
{ 
    if (key is string && key.Equals("stat")) 
    { 
     this.stat = (int)value; 
    } 
} 
+0

感謝您的響應,因爲它會工作,但我會公開這些類,它不會作爲一個字典的意義。人們應該能夠在不知道字典的情況下創建它們。不過謝謝。 – Michael

0

詞典不更新前值屬性的值。當您存儲foo.CodeMap["stat"] = 27;時,foo.CodeMap["stat"](它的值爲Status)的較早值將被27覆蓋。

字典中由鍵(在您的情況下爲「stat」)標識的位置是數據存儲區,即CodeMap["stat"]是數據的存儲位置,而不是相反方向。您在此位置存儲的任何內容都會覆蓋以前的數據。

你應該詳細說明你正在嘗試解決的實際問題。您的問題對於讀者推斷實際需求/問題還不夠清楚。

+0

我想要做的是給一個隨機字符串能夠知道哪些屬性更新。我正在反序列化一些看起來像「stat 200」的數據,並且有很多不同的數據文件。每個文件對應一個不同的類。我想要一個通用的Deserialize ():其中T:Data,new()。反序列化方法在看到代碼時應該能夠更新T中的屬性。我將每種類型的數據都填充到字典中,作爲數據的一個子類。在我正在做的反序列化方法if(dataFile.CodeMap.ContainsKey(keyReadFromFile)){dataFile.CodeMap [keyFromDataFile] = dataValue; } – Michael

0

另一種方法是使用ExpandoObject。 這是一種方式結合到詞典樣品:

public class Foo 
{ 
    public Foo() 
    { 
     Properties = new ExpandoObject(); 
     Status = 0; 
     Version = 0; 
    } 

    public dynamic Properties { get; set; } 

    public IDictionary<string, object> CodeMap 
    { 
     get { return Properties; } 
    } 

    private int _status; 
    public int Status 
    { 
     get { return _status; } 
     set 
     { 
      _status = value; 
      Properties.stat = _status; 
     } 
    } 

    private int _version; 
    public int Version 
    { 
     get { return _version; } 
     set 
     { 
      _version = value; 
      Properties.ver = _version; 
     } 
    } 
} 

使用:

var foo = new Foo 
       { 
        Status = 1, 
        Version = 2 
       }; 

Console.WriteLine(foo.CodeMap["stat"]); 
Console.WriteLine(foo.CodeMap["ver"]); 
Console.WriteLine(foo.Properties.stat); 
Console.WriteLine(foo.Properties.ver); 
1

對於將來的觀衆,在簡單的情況下它的足夠使用功能 '< 'T'>'。

public string TestProperty {get; set;} 
    public Dictionary<int, Func<string>> dictionary; 

    Constructor() 
    { 
    dictionary = new Dictionary<int, Func<string>> 
    { 
     {1,()=>TestProperty } 
    } 
    } 

當使用這樣的:

dictionary[1]() or dictionary[1].Invoke() 

它返回的屬性在目前的實際值。