2012-07-05 34 views
5

tôi có một loạt các lớp kinh doanh với autoproperties:Refactor C# thuộc tính tự động cho các trường và thuộc tính getter/setter?

public class A { 

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

} 

Do việc áp dụng tiến hóa, có một yêu cầu mới để cho phép theo dõi những thay đổi của các tài sản, để gửi đến các cửa hàng ủng hộ chỉ thay đổi dữ liệu.

Để đạt được mục tiêu này, tôi phải chuyển đổi tất cả các thuộc tính đến lĩnh vực bất động sản + như thế này:

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 
    } 
} 

Có cách nào để nhanh chóng cấu trúc lại mã của tôi để tránh phải tự thay đổi các thuộc tính?

+3

Nếu tất cả các lớp học kinh doanh của bạn chỉ đơn giản là các lớp có tính tự động và không có gì khác, tôi sẽ chuyển đổi sang sử dụng [mẫu T4] (http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx) để tạo lớp học của bạn.Sau đó, nó là một sự thay đổi tầm thường để định dạng lại tất cả chúng như trên. – mellamokb

+5

Regex thay thế có thể làm việc - cũng Resharper có một cái gì đó như thế này, nhưng nó có thể yêu cầu bạn phải làm mỗi một lần lượt. Ngoài ra một mẫu CodeSmith sẽ sắp xếp mà ra trong thời gian không giả định bạn biết làm thế nào để sử dụng nó. Nếu không, tôi sẽ tạo một đoạn mã có cấu trúc đúng và chỉ cần làm lại các thuộc tính. Đoạn mã sẽ điền vào tất cả các bit mà tôi cho là, nhưng nó vẫn là một công việc thủ công! Tôi sẽ đi cho regex ... hoặc như mellamokb nói, một mẫu T4, tôi đã có thành công tốt với họ cho những thứ đơn giản – Charleh

+0

Bạn có sử dụng Resharper? Nếu vậy, đó là một phím tắt, và ai đó đã mở rộng nó để tự động thêm hỗ trợ INotifyPropertyChanged: https://bitbucket.org/tgmayfield/resharper.tgmcontrib –

Trả lời

1

Bạn luôn có thể chỉ cần tạo một phương pháp chung chung mà sẽ thực hiện nhiệm vụ và gọi SetChange

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

Bạn vẫn sẽ cần phải có một trường quay tư nhân. lớp học của bạn sẽ giống như thế:

public class A { 

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

Ngay cả khi điều này sẽ đơn giản hóa mã, điều này vẫn sẽ yêu cầu cập nhật thủ công tất cả các thuộc tính . –

+0

Tôi đã đặt câu trả lời của bạn làm giải pháp, bởi vì tôi thực sự sử dụng phương pháp này. Thực tế, tôi đã thực hiện một số bước: Đầu tiên tôi sử dụng CodeRush XPress để cấu trúc lại autoproperty của tôi thành một thuộc tính với get/set trên một trường sao lưu. Sau đó, tôi đã thêm phương thức của bạn vào lớp cơ sở của tôi. Cuối cùng, tôi sử dụng Visual Studio Replace w/Reg ex để trích xuất: '_ (\ w +) = value' bởi' SetValue (ref _ $ 1, value, "$ 1"); '. Regex phù hợp với bất kỳ thiết lập trường nào và thay thế nó bằng cách gọi đến phương thức của bạn. –

+0

Thậm chí tốt hơn: tìm kiếm: 'public ([\ w?] +) (\ W +) {get; bộ; } 'và thay thế bằng' public $ 1 $ 2 {get {return m_ $ 2;} đặt {SetValue (ref m_ $ 2, value, "$ 2");}} riêng $ 1 m_ $ 2; '. Điều này sẽ tránh bước refactor, và tự động giải nén autoprop. –

0

ReSharper có thể thực hiện việc này nhưng không sửa đổi thiết lập.

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

Không có cách nào trong IDE để làm điều này, nhưng nếu bạn cần phải thay thế tất cả các thuộc tính X, tôi sẽ viết một ứng dụng console ngắn để làm điều đó.

Quá trình này sẽ là:

  • lặp qua tất cả các file trong thư mục phù hợp * .cs
  • Foreach tập tin, regex tìm và thay thế tài sản cũ cho cú pháp thuộc tính mới

Sử dụng regex để phù hợp là rất mạnh mẽ. Regex có thể được sử dụng trong VS2010 để thực hiện thao tác tìm/thay thế. Nếu bạn cố gắng tìm kiếm này (với regex kích hoạt)

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

Nó sẽ phù hợp với tính chất như thế này

public Type Foo { get; set; } 

Trong ứng dụng giao diện điều khiển của bạn tìm thấy tất cả các dòng mã phù hợp trên, sau đó bắt đầu tách chúng ra thành Công cụ sửa đổi, Loại, Tên thuộc tính và cuối cùng thay thế toàn bộ khối bằng một cái gì đó như thế này

// 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; 
     } 
    } 
} 

Cuối cùng tôi sẽ ủng hộ việc sao lưu mã của bạn hoặc chạy thử nghiệm này và thử nghiệm trước khi kiểm tra !!

+0

"lấy một bản sao lưu", ++++ 1 :) –

+0

Lol, nghe như một điều ngu ngốc để nói nhưng bạn không bao giờ biết đúng? –

+0

Tôi đã học cách làm điều đó lần đầu tiên tôi sử dụng notepad ++ để thay thế tất cả các lần xuất hiện của A thành B trong một giải pháp dự án. :) –

0

Có lẽ không có cách nào trực tiếp để làm điều này với khúc xạ. Nếu đây là vấn đề của tôi. Tôi sẽ tạo mã để tạo điều này:

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

Bây giờ chỉ cần cắm nó vào và chug nó ra.

Các vấn đề liên quan