2011-11-30 31 views
11

Nói rằng tôi có một lớp học với bất kỳ số lượng các thuộc tính của bất kỳ loạiThêm thuộc tính bổ sung cho mỗi thuộc tính của một lớp

public class Test 
{ 
public string A {get;set;} 
public object B {get;set;} 
public int C {get;set;} 
public CustomClass D {get;set;} 
} 

Tôi muốn tất cả các đối tượng bên trong lớp này có một khái niệm về 'lỗi' và 'cảnh báo'. Ví dụ, dựa trên một số điều kiện trong một lớp khác, tôi có thể muốn thiết lập một cảnh báo về thuộc tính A, và sau đó hiển thị thông tin đó trong GUI. GUI không phải là mối quan tâm của tôi; thay vì làm thế nào tôi nên đặt cảnh báo này? Tôi rất thích để có thể làm điều gì đó như:

Đối với mỗi tài sản trong một lớp học, thêm một 'Cảnh báo' và 'Lỗi' tài sản đó mà tôi có thể làm ..

Test t = new Test(); 
t.A.Warning = "This is a warning that the GUI will know to display in yellow". 
t.B.Error = null; 

tốt nhất là gì cách để làm điều này? Sẽ tốt hơn nếu tôi có thể thêm thuộc tính tùy chỉnh vào mỗi thuộc tính của lớp sẽ thêm các thuộc tính bổ sung này và cho phép tôi truy cập chúng một cách rõ ràng.

Tôi đã thấy các giải pháp thêm từ điển vào lớp cha (Test) và sau đó chuyển vào chuỗi khớp với tên thuộc tính hoặc sử dụng sự phản chiếu để lấy tên thuộc tính và chuyển nó vào, nhưng tôi muốn .

Trả lời

8

Bạn có thể thêm một thuộc tính tùy chỉnh bạn muốn thuộc tính và sau đó sử dụng một phương thức mở rộng trên đối tượng để truy cập các thuộc tính đó.

Something như thế này nên làm việc

Trước tiên, bạn sẽ cần phải tạo lớp thuộc tính của bạn

[AttributeUsage(AttributeTargets.All/*, AllowMultiple = true*/)] 
public class WarningAttribute : System.attribute 
{ 
    public readonly string Warning; 

    public WarningAttribute(string warning) 
    { 
     this.Warning = warning; 
    }  
} 

More Reading Here

Sử dụng nó như vậy

[WarningAttribute("Warning String")] 
public string A {get;set;} 

Sau đó truy cập vào nó như vậy MSDN Article

public static string Warning(this Object object) 
{ 
    System.Attribute[] attrs = System.Attribute.GetCustomAttributes(object); 

    foreach (System.Attribute attr in attrs) 
     { 
      if (attr is WarningAttrbiute) 
      { 
       return (WarningAttribute)attr.Warning; 
      } 
     } 
} 

Sau đó, nếu bạn có một mục mà bạn muốn truy cập vào các cảnh báo trên bạn chỉ có thể gọi

test.A.Warning; 

Nếu bạn đang muốn thiết lập các chuỗi cảnh báo bạn có thể thực hiện một số loại setter cho một chút sạch sẽ hơn. Có khả năng thông qua việc thiết lập một đối tượng thứ cấp hoặc loại thuộc tính.


Một phương pháp khác để thực hiện điều này sẽ là thay vì chỉ sử dụng stringobject bạn có thể tạo một kiểu tùy chỉnh chung để xử lý đó thiết lập tài sản.

Something như

public class ValidationType<T> 
{ 
    public T Value {get; set;} 
    public string Warning {get; set;} 
    public string Error {get; set;} 

    public ValidationType(T value) 
    { 
     Value = value; 
    } 
} 

Sử dụng như

var newWarning = new ValidationType<string>("Test Type"); 
newWarning.Warning = "Test STring"; 
Console.WriteLine("newWarning.Value"); 

+0

Cảm ơn bạn đã phản hồi. Tôi nghĩ rằng tôi sẽ thực hiện điều này. Tôi không thích phải sử dụng newWarning.Value để thực sự truy cập vào các thuộc tính chuỗi, nhưng có vẻ như tôi sẽ phải hy sinh một số tiện lợi ở đâu đó. – user981225

1

Thứ nhất, các thuộc tính không thể sửa đổi đối tượng được đặt trên đó. Trừ khi bạn kết hợp chúng với AOP. Tôi sẽ đề nghị sử dụng một lớp bọc xung quanh lớp bằng cách kế thừa nó, miễn là các lớp không được niêm phong. Nếu chúng được niêm phong, sau đó bạn sẽ phải viết một lớp bao bọc thực tế, bỏ qua tất cả các hoạt động, ngoại trừ các thao tác bạn thêm vào một trường riêng tư là một thể hiện của lớp mà bạn gói.

Chỉnh sửa: Để dễ sử dụng, phương pháp tiện ích mở rộng được đề xuất có lẽ là giải pháp tốt nhất.

2

Nếu bạn có thể thoát ra bằng phương pháp thay vì thuộc tính, bạn có thể tạo phần mở rộng cho đối tượng - nhưng sau đó sẽ khó thu hẹp nó chỉ sử dụng cho một số lớp.

Cái gì như:

public static void Warning(this object target, string message) 
{ 
... 
} 

public static String GetWarning(this object target) 
{ 
} 

Tất nhiên nó sẽ rất khó để duy trì như một lời cảnh báo trong trạng thái của đối tượng, nhưng sau đó bạn có thể sử dụng một số từ điển vv

+0

Cảm ơn bạn đã đăng bài nhưng tôi muốn tránh giải pháp này. Tôi muốn các tài sản thực tế để biết có hay không nó có một lỗi, không cho các đối tượng phụ huynh phải lặp qua một từ điển của chuỗi (ví dụ). – user981225

2

Thay vì cố gắng để gán các thuộc tính, tôi sẽ đề nghị thêm một tập hợp các đặc tính lỗi/cảnh báo cho một lớp cơ sở mà bạn các đối tượng kinh doanh được kế thừa từ.

Bằng cách này, bạn có thể cung cấp thông tin chi tiết hơn, bạn có thể xóa chúng khi chúng được hiển thị cho người dùng và nếu bạn đang gửi dữ liệu qua "dây" (dịch vụ web, dịch vụ wcf), lỗi có thể di chuyển với các đối tượng của bạn thay vì yêu cầu xử lý đặc biệt để gửi các thuộc tính.

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