2012-07-05 125 views
5

我有autoproperties一堆公務艙:重構C#自動屬性字段和getter/setter屬性?

public class A { 

    public int Id { get; set; } 
    public string Title { get; set;} 

} 

由於應用程序的發展,出現了新的要求,以使跟蹤性能的變化,以便發送到後備存儲唯一改變的數據。

爲了達到這個目標,我必須對所有屬性轉換爲場+屬性是這樣的:

public class A { 

    private int m_Id; 
    public int Id { 
     get { return m_Id; } 
     set { 
      if(m_Id != value){ 
       SetChanged("Id"); 
       m_Id = value; 
      } 
     } 
    } 
    private string m_Title; 
    public string Title 
    { 
     get { return m_Title; } 
     set { 
      if(m_Title != value){ 
       SetChanged("Title"); 
       m_Title = value; 
      } 
     } 
    } 

    protecte void SetChanged(string propertyName) { 
     // Not important here 
    } 
} 

有沒有一種方法能夠快速重構我的代碼,以避免手動更改屬性?

+3

如果您的所有業務類都只是具有自動屬性的類而沒有其他內容,那麼我會轉換爲使用[T4模板](http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx)來生成您的類。然後像上面那樣重新格式化它們是一個微不足道的變化。 – mellamokb 2012-07-05 15:37:46

+5

正則表達式替換可能工作 - 也Resharper有這樣的事情,但它可能需要你依次做每一個。另外一個CodeSmith模板會在假設你知道如何使用它的情況下進行排序。否則,我會創建一個具有正確結構並重新執行屬性的代碼片段。代碼段會填入所有的位,但它仍然是一個手動工作!我會選擇正則表達式......或者像mellamokb所說的那樣,T4模板,我已經在他們的簡單的東西上取得了很好的成功 – Charleh 2012-07-05 15:38:36

+0

您使用Resharper嗎?如果是這樣,它是一個快捷方式,有人已經擴展它來自動添加INotifyPropertyChanged支持:https://bitbucket.org/tgmayfield/resharper.tgmcontrib – 2012-07-05 15:39:32

回答

1

你可以隨時創建一個通用的方法,將做分配和調用SetChange

void SetChangeIfNeeded<T>(ref T field, T value, string propertyName) 
{ 
    if (!EqualityComparer<T>.Default.Equals(field, value)) 
    { 
     field = value; 
     SetChanged(property); 
    } 
} 

你仍然需要有一個私人返場。您的類看起來是這樣的:

public class A { 

    private int m_id 
    public int Id 
    { 
     get { return m_id }; 
     set { SetChangeIfNeeded<int>(ref m_id, value, "Id"); } 
    } 
} 
+0

即使這將簡化代碼,仍然需要手動更新所有屬性。 – 2012-07-06 07:20:07

+0

我已經將答案設置爲解決方案,因爲我實際上使用了這種方法。實際上,我已經執行了一些步驟:首先,我使用CodeRush XPress將我的autoproperty重構爲通過後臺字段獲取/設置的屬性。然後,我將你的方法添加到我的基類中。最後,我使用Visual Studio Replace w/Reg ex通過'SetValue(ref _ $ 1,value,「$ 1」);'提取'_(\ w +)= value'。正則表達式匹配任何字段setter,並將其替換爲您的方法的調用。 – 2012-07-06 08:28:50

+0

更好:搜索:'public([\ w?] +)(\ w +){get;組; }'並替換爲'public $ 1 $ 2 {get {return m_ $ 2;} set {SetValue(ref m_ $ 2,value,「$ 2」);}} private $ 1 m_ $ 2;'。這將避免重構步驟,並自動提取自動駕駛儀。 – 2012-07-06 08:44:10

0

ReSharper可以做到這一點,但不會修改setter。

public string Title { 
    get { return m_title; } 
    set { m_title = value; } 
} 
3

有在IDE中要做到這一點沒辦法,但是如果你需要更換所有的X性質,我會寫一個簡短的控制檯應用程序來做到這一點。

的過程會是:

  • 遍歷所有目錄中的文件匹配*的.cs
  • 的foreach文件,正則表達式查找和替換舊屬性新屬性的語法

使用正則表達式來比賽非常強大。正則表達式可以在VS2010中使用來執行查找/替換操作。如果你在找到這個(啓用正則表達式)

{(public|private|internal|protected)}:b{[a-zA-Z0-9]+} 
:b{[a-zA-Z0-9]+}:b\{ get; set; \} 

它將匹配這樣

public Type Foo { get; set; } 

屬性在控制檯應用程序找到匹配上面的所有代碼行,然後開始分裂他們成修改,類型,屬性名和最後的東西更換整個塊這樣

// PS: this is pseudocode ;-) or could be your new property template 
private [Type] m_[PropertyName].ToPascaleCase 
public [Type] PropertyName 
{ 
    get { return m_[PropertyName].ToPascaleCase; } 
    set 
    { 
     if(m_[PropertyName].ToPascaleCase != value){ 
      SetChanged([PropertyName]); 
      m_[PropertyName].ToPascaleCase = value; 
     } 
    } 
} 

最後我主張把你的代碼的備份或運行該測試在登記之前進行Fline和測試!

+0

「採取備份」,++++ 1 :) – 2012-07-06 07:21:09

+0

大聲笑,聽起來像一個愚蠢的事情說,但你永遠不知道對不對? – 2012-07-06 09:50:54

+0

我已經學會了這樣做,我第一次使用記事本++在項目解決方案中將A的所有出現替換爲B. – 2012-07-06 09:54:30

0

可能沒有直接的折射方法。如果這是我的問題。我會使代碼生成這個:

public string MakePropertyBigger(string varName, string propName, string dataType) 
{ 
    string output = ""; 
    output += string.Format("private {0} {1};", dataType, varName) + Environment.NewLine; 
    output += string.Format("public {0} {1}", dataType, propName) + Environment.NewLine; 
    output += "{" + Environment.NewLine; 
    output += string.Format("get { return {0}; }", varName) + Environment.NewLine; 
    output += string.Format("set { if({0} != value){ SetChanged(\"{1}\");", varName, propName) + Environment.NewLine; 
    output += string.Format("{0} = value; }", varName) + Environment.NewLine; 
    output + "}" + Environment.NewLine + "}"; 

現在只需將其插入並突出顯示。