2010-05-11 31 views
6

Phím tắt ngôn ngữnhã Xử lý lặp đi lặp lại Mã số tài sản trong C#

public string Code 
{ 
    get; 
    set; 
} 

tiết kiệm một chút gõ khi xác định tính chất tầm thường trong C#.

Tuy nhiên, tôi thấy mình viết mã đặc tính lặp đi lặp lại, không phải là khá tầm thường mà vẫn tuân theo một mẫu rõ ràng, ví dụ:

public string Code 
{ 
    get { return code; } 
    set 
    { 
     if (code != value) 
     { 
      code = value; 
      NotifyPropertyChanged("Code"); 
     } 
    } 
} 

Tôi chắc chắn có thể xác định đoạn mã Visual Studio để giảm nhập. Tuy nhiên, nếu tôi cần thêm thứ gì đó vào mẫu của mình, tôi phải quay lại và thay đổi khá nhiều mã hiện có.

Có cách tiếp cận trang nhã hơn không? Đoạn trích có phải là cách tốt nhất để đi không?

UPDATE:

Như một sự cải thiện nhanh chóng cho ngay bây giờ, tôi đã chỉnh sửa (sau khi thực hiện một bản sao lưu)

C: \ Program Files \ Microsoft Visual Studio 10.0 \ VC# \ Snippets \ 1033 \ Refactoring \ EncapsulateField.snippet

(đường dẫn dành cho VS 2010)

để phản ánh mẫu hiện tại của tôi. Bây giờ, công cụ tái cấu trúc dựng sẵn sử dụng mẫu của tôi để tạo thuộc tính từ một trường. Hạn chế: Thay đổi toàn cầu cho Visual Studio, không thể thay đổi trước mã thuộc tính hiện tại.

Trả lời

7

Điều này được biết là Aspect Oriented Programming (AOP).

Scott Hanselman gần đây đã làm một cuộc phỏng vấn với người tạo ra LinFu, Philip Laureano về chủ đề này. (link)

Có một số công cụ AOP trên mạng, tùy theo nhu cầu của bạn.

Và cuối cùng, một số hiện thực của một lớp INotifyPropertyChanged sử dụng các công cụ trên:

Cập nhật năm 2013: Kể từ khi câu trả lời ban đầu này, tôi đã đi qua một giải pháp mà làm mọi thứ tôi cần rất dễ dàng.

PropertyChanged.Fody (trước đây là NotifyPropertyWeaver) là một trình biên dịch IL sau biên dịch sẽ tự động chèn mã thay đổi thuộc tính cho bạn. Đây là giải pháp ưa thích của tôi cho INotifyPropertyChanged.

+0

+1 Dễ dàng câu trả lời tốt nhất và phù hợp nhất! – Pat

-1

một mẫu rất phổ biến. Snippet là ok, nhưng cậu bé, nó sẽ không được tuyệt vời nếu MS tạo ra một số đường cú pháp cho các thông báo thay đổi sở hữu ô tô ....

Something như ....

public string Code { get; setwithnotify; } 

Đó thực sự sẽ rất tốt đẹp.

+0

Có mà sẽ xử lý mô hình đặc biệt này, mặc dù vẫn còn lá vấn đề chung của lặp đi lặp lại một số mẫu tùy ý - lý tưởng với khả năng chèn sửa đổi cho một định tài sản - chưa được giải quyết. –

+0

Đây không phải là câu trả lời mà là thảo luận, vì vậy nó sẽ được đặt tốt hơn làm nhận xét cho câu hỏi gốc. Bên cạnh đó, tôi không nghĩ rằng nó là một ý tưởng tốt để nướng các khái niệm từ khuôn khổ quá nhiều vào cú pháp C#. Một khi INotifiyPropertyChange đi ra khỏi phong cách (chỉ cần nhìn vào thuộc tính phụ thuộc), chúng tôi còn lại với một khái niệm di sản. – jpierson

2

Tôi chưa tự làm, nhưng tôi đã thấy khuôn khổ tiêm phụ thuộc được sử dụng cho tác vụ cụ thể này.

Goes và Googles

Ahaha!

Dường như, sử dụng Unity DI framework, bạn có thể tiêm INotifyPropertyChanged vào thuộc tính tự động. Hãy xem bài đăng trên blog tuyệt vời này: http://shecht.wordpress.com/2009/12/12/inotifypropertychanged-with-unity-interception-aop/

Điều này nhắc tôi về một HanselMinutes gần đây, nơi Scott đang nói chuyện với một anh chàng về Lập trình hướng Aspect (AOP), nơi loại tiêm này là nơi rất phổ biến.

+0

DI có vẻ rất hứa hẹn. Mặc dù không được nêu trong câu hỏi, tôi đang làm việc với Silverlight vào lúc này. Tự hỏi nếu Unity 2.0 cho Silverlight cũng hỗ trợ mẫu đó (không biết những gì họ phải bỏ ra so với phiên bản tiêu chuẩn). –

1

Tôi ghét viết mã đó!

Trong quá khứ, để giải quyết vấn đề này, tôi đã triển khai một máy phát mã để tạo lớp partial với định nghĩa thuộc tính.

+0

Tôi đã tự tạo mã từ các mô hình UML trong quá khứ. Đó là một cách tiếp cận tuyệt vời khi dự án là "đủ lớn" để đảm bảo một cách tiếp cận dựa trên mô hình và tạo ra trình tạo mã. Với công cụ tạo mô hình ngày càng mạnh mẽ/tích hợp, ngưỡng "đủ lớn" tiếp tục giảm. –

+0

@Eric: Cá nhân, tôi sẽ tránh UML và toàn bộ chi phí trí tuệ của nó. Tôi nghĩ mục tiêu của bạn ở đây rất đơn giản: các lớp học với các thuộc tính thông báo về thay đổi. Một giải pháp đơn giản có thể là một kịch bản PowerShell cho phép bạn viết: 'class C {property string Code; } 'và tạo ra một lớp một phần. Tôi đã làm điều này trước khi tôi cũng muốn có một giao diện thông thạo cho lớp. –

3

Đây là một cái gì đó tôi chế nhạo như một bài tập. Được lấy cảm hứng từ số blog post của Jon Skeet.

public static class ObjectExtensions { 
    public static string GetPropertyNameAndValue<T>(this T obj, out object value) { 
     System.Reflection.PropertyInfo[] objGetTypeGetProperties = obj.GetType().GetProperties(); 
     if(objGetTypeGetProperties.Length == 1) { 
      value = objGetTypeGetProperties[0].GetValue(obj, null); 
      return objGetTypeGetProperties[0].Name; 
     } else 
      throw new ArgumentException("object must contain one property"); 
    } 
} 

class Whatever { 
protected void ChangeProperty<T>(object property, T newValue, Action change) { 
    object value; 
    var name = property.GetPropertyNameAndValue(out value); 

    if(value == null && newValue != null || value != null && !value.Equals(newValue)) { 
     change(); 
     OnPropertyChanged(name); 
    } 
} 

private string m_Title; 
public string Title { 
    get { return m_Title; } 
    set {ChangeProperty(
       new { Title }, //This is used to dynamically retrieve the property name and value 
       value, // new value 
       () => m_Title = value); //lambda to change the value 
    } 
} 
} 

Đây là điều tốt nhất tôi có thể nghĩ ra. Hiệu suất thời gian chạy có thể đạt khá cao, nhưng tôi chưa thử nghiệm nó.

Một chút giải thích về giải pháp trên. new { Title } tạo ra một đối tượng ẩn danh và do projecttion (được giới thiệu trong .NET 3.5) đối tượng mới được tạo có một thuộc tính duy nhất được gọi là Title và giá trị là giá trị của thuộc tính gốc của đối tượng gốc là Title.

GetPropertyNameAndValue là chức năng thực hiện tất cả công việc thú vị - nó truy xuất tên và giá trị của thuộc tính ngoài đối tượng ẩn danh. ChangeProperty sau đó thực hiện kiểm tra bình đẳng và gọi lambda thực sự thay đổi thuộc tính và cũng gọi NotifyPropertyChanged.

Hoặc bạn chỉ có thể làm một đoạn như sau:

<?xml version="1.0" encoding="utf-8" ?> 
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> 
    <CodeSnippet Format="1.0.0"> 
     <Header> 
      <Title>propfullinotify</Title> 
      <Shortcut>propfullinotify</Shortcut> 
      <Description>Code snippet for property and backing field with INotifyPropertyChanged</Description> 
      <Author>Microsoft Corporation</Author> 
      <SnippetTypes> 
       <SnippetType>Expansion</SnippetType> 
      </SnippetTypes> 
     </Header> 
     <Snippet> 
      <Declarations> 
       <Literal> 
        <ID>type</ID> 
        <ToolTip>Property type</ToolTip> 
        <Default>int</Default> 
       </Literal> 
       <Literal> 
        <ID>property</ID> 
        <ToolTip>Property name</ToolTip> 
        <Default>MyProperty</Default> 
       </Literal> 
       <Literal> 
        <ID>field</ID> 
        <ToolTip>The variable backing this property</ToolTip> 
        <Default>myVar</Default> 
       </Literal> 
      </Declarations> 
      <Code Language="csharp"> 
     <![CDATA[private $type$ $field$; 

    public $type$ $property$ 
    { 
     get { return $field$;} 
     set { 
     if ($field$ != value) 
     { 
     $field$ = value; 
     if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("$property$")); 
     } 
    } 
    } 
    $end$]]> 
      </Code> 
     </Snippet> 
    </CodeSnippet> 
</CodeSnippets> 
+0

Đó là một cách tiếp cận thú vị để sử dụng các phương pháp mở rộng, mặc dù tôi không thực hiện đầy đủ việc thực hiện. Phần "mới {Title}, tựa đề" làm gì? Tại sao "giá trị" không được tham chiếu? –

+0

Hehe, nó thực sự là một cái gì đó Jon Skeet đã đưa ra với con đường trở lại khi nào, và là một cách để có được tên của tài sản trong thời gian chạy. 'giá trị' không được tham chiếu thực sự là một lỗi, do nâng nó từ một nơi khác. Tôi sẽ sửa chữa nó và mở rộng trên các giải pháp. –

+0

Cảm ơn bạn đã làm rõ. Chắc chắn là một cách tiếp cận thú vị! –

-6

Để trả lời các câu hỏi chung về mã repetetive, không chỉ các trường hợp thông báo thay đổi sở hữu:

chắc. Đây là một trường hợp hoàn hảo cho một macro.

Oh wait. C# không có macro. Bởi vì tất nhiên, macro là ác và không phải là giải pháp tốt nhất cho bất kỳ vấn đề lập trình nào.

Trừ khi bạn chèn tiền xử lý vào bản dựng của mình.

+1

-1: Không hữu ích. –

+1

Không hữu ích (và thậm chí sẽ không là một gợi ý tốt nếu câu hỏi là trong c + +) –

0

Cảm ơn mọi người đã trả lời. Tôi đã upvoted câu trả lời hữu ích. Tuy nhiên, sau khá nhiều nghiên cứu, tôi đã tin rằng câu trả lời hay nhất (ít nhất là đối với tôi và cách tôi phát triển phần mềm) là mô hình hóa các lớp trong Visual Studio và sử dụng T4 để tạo mã một phần các lớp thực thi thuộc tính mã.

Xem http://msdn.microsoft.com/en-us/library/ee329480.aspx

+0

Đó là những gì Jay Bazuzi đề xuất đúng không? – jpierson

1

Có một cái nhìn tại NotifyPropertyWeaver: https://github.com/SimonCropp/NotifyPropertyWeaver

+1

NotifyPropertyWeaver đã không còn được dùng cho [PropertyChanged.Fody] (https://github.com/fody/propertychanged). Xem http://simoncropp.com/fodyandnotifypropertyweaver –

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