Các thuộc tính trong .NET là gì?


206

Các thuộc tính trong .NET là gì, chúng tốt cho cái gì và làm cách nào để tạo các thuộc tính của riêng tôi?

Câu trả lời:


146

Metadata. Dữ liệu về các đối tượng / phương thức / thuộc tính của bạn.

Ví dụ: tôi có thể khai báo một Thuộc tính có tên: DisplayOrder để tôi có thể dễ dàng kiểm soát các thuộc tính thứ tự nào sẽ xuất hiện trong Giao diện người dùng. Sau đó tôi có thể nối nó vào một lớp và viết một số thành phần GUI trích xuất các thuộc tính và sắp xếp các thành phần UI một cách thích hợp.

public class DisplayWrapper
{
    private UnderlyingClass underlyingObject;

    public DisplayWrapper(UnderlyingClass u)
    {
        underlyingObject = u;
    }

    [DisplayOrder(1)]
    public int SomeInt
    {
        get
        {
            return underlyingObject .SomeInt;
        }
    }

    [DisplayOrder(2)]
    public DateTime SomeDate
    {
        get
        {
            return underlyingObject .SomeDate;
        }
    }
}

Do đó, đảm bảo rằng someInt luôn được hiển thị trước someDate khi làm việc với các thành phần GUI tùy chỉnh của tôi.

Tuy nhiên, bạn sẽ thấy chúng được sử dụng phổ biến nhất bên ngoài môi trường mã hóa trực tiếp. Ví dụ, Windows Designer sử dụng chúng rộng rãi để nó biết cách xử lý các đối tượng được tạo tùy chỉnh. Sử dụng BrowseableAttribution như vậy:

[Browsable(false)]
public SomeCustomType DontShowThisInTheDesigner
{
    get{/*do something*/}
}

Yêu cầu nhà thiết kế không liệt kê điều này trong các thuộc tính có sẵn trong cửa sổ Thuộc tính tại thời điểm thiết kế chẳng hạn.

Bạn cũng có thể sử dụng chúng cho các hoạt động tạo mã, biên dịch trước (như Post-Sharp) hoặc các hoạt động trong thời gian chạy như Reflection.Emit. Ví dụ, bạn có thể viết một chút mã để định hình một cách trong suốt mỗi cuộc gọi mà mã của bạn thực hiện và nhân đôi mã đó. Bạn có thể "từ chối" thời gian thông qua một thuộc tính mà bạn đặt trên các phương thức cụ thể.

public void SomeProfilingMethod(MethodInfo targetMethod, object target, params object[] args)
{
    bool time = true;
    foreach (Attribute a in target.GetCustomAttributes())
    {
        if (a.GetType() is NoTimingAttribute)
        {
            time = false;
            break;
        }
    }
    if (time)
    {
        StopWatch stopWatch = new StopWatch();
        stopWatch.Start();
        targetMethod.Invoke(target, args);
        stopWatch.Stop();
        HandleTimingOutput(targetMethod, stopWatch.Duration);
    }
    else
    {
        targetMethod.Invoke(target, args);
    }
}

Khai báo chúng là dễ dàng, chỉ cần tạo một lớp kế thừa từ Thuộc tính.

public class DisplayOrderAttribute : Attribute
{
    private int order;

    public DisplayOrderAttribute(int order)
    {
        this.order = order;
    }

    public int Order
    {
        get { return order; }
    }
}

Và hãy nhớ rằng khi bạn sử dụng thuộc tính, bạn có thể bỏ qua "thuộc tính" hậu tố, trình biên dịch sẽ thêm nó cho bạn.

LƯU Ý: Các thuộc tính không tự làm bất cứ điều gì - cần phải có một số mã khác sử dụng chúng. Đôi khi mã đó đã được viết cho bạn nhưng đôi khi bạn phải tự viết nó. Ví dụ, trình biên dịch C # quan tâm đến một số và một số khung công tác nhất định sử dụng một số (ví dụ: NUnit tìm kiếm [TestFixture] trên một lớp và [Kiểm tra] trên phương thức thử nghiệm khi tải một cụm).
Vì vậy, khi tạo thuộc tính tùy chỉnh của riêng bạn, hãy lưu ý rằng nó sẽ không ảnh hưởng đến hành vi của mã của bạn. Bạn sẽ cần phải viết phần khác kiểm tra các thuộc tính (thông qua sự phản chiếu) và hành động trên chúng.


32
Để biết giá trị của nó, đây là danh sách tất cả các thuộc tính .NET (tích hợp sẵn): msdn.microsoft.com/en-us/l
Library / aa311259 (VS.71) .aspx

1
Bạn sẽ sử dụng "someProfilingMethod" như một thuộc tính như thế nào?
RayLoveless

@RayLovless không phải là một thuộc tính, someProfilingMethod là mã thiết bị đang tìm kiếm các thuộc tính định hình. Cụ thể trong ví dụ tôi đã cho nó tìm kiếm một thuộc tính "từ chối" (NoTimingAttribution) trái ngược với thuộc tính "chọn tham gia". Ý tưởng là nó nhân mọi thứ.
Quibbledome

@Quibbledome bạn có thể thêm một cái gì đó như "Các thuộc tính không tự làm bất cứ điều gì - cần phải có một số mã khác để sử dụng chúng (trình biên dịch quan tâm đến cặp đôi, các khung khác nhau sử dụng một số). Chỉ cần tạo thuộc tính sẽ không ảnh hưởng đến hành vi của mã - bạn cần viết phần khác kiểm tra các thuộc tính (thông qua sự phản chiếu) và hành động theo chúng ". (hoặc tôi có thể làm điều đó nếu bạn ổn). Nhiều người mong đợi các thuộc tính để làm việc kỳ diệu và không có câu trả lời nào ở đây làm rõ điều đó. (hoặc chỉ liên kết đến stackoverflow.com/questions/4879521/ mà bao gồm nó)
Alexei Levenkov

chỉ khi bạn ngừng sử dụng Bing. Không j / k Tôi sử dụng DuckDuckGo làm chính, chủ yếu sử dụng Bing iirc. :)
Quibbledome

36

Nhiều người đã trả lời nhưng cho đến nay vẫn chưa có ai đề cập đến điều này ...

Các thuộc tính được sử dụng rất nhiều với sự phản ánh. Phản xạ đã khá chậm.

Nó là rất đáng giá đánh dấu thuộc tính tùy chỉnh của bạn như là sealedlớp học để cải thiện hiệu suất thời gian chạy của họ.

Nó cũng là một ý tưởng tốt để xem xét nơi nào sẽ thích hợp để sử dụng vị trí như vậy và thuộc tính của bạn (!) Để chỉ ra điều này thông qua AttributeUsage. Danh sách các tập quán thuộc tính có sẵn có thể làm bạn ngạc nhiên:

  • hội,, tổ hợp
  • Mô-đun
  • Lớp học
  • Cấu trúc
  • Enum
  • Constructor
  • phương pháp
  • Bất động sản
  • Cánh đồng
  • Biến cố
  • Giao diện
  • Tham số
  • Đại biểu
  • Trả lại giá trị
  • Thông số chung
  • Tất cả

Cũng thật tuyệt khi thuộc tính AttributionUsage là một phần của chữ ký của thuộc tính AttributionUsage. Whoa cho phụ thuộc tròn!

[AttributeUsageAttribute(AttributeTargets.Class, Inherited = true)]
public sealed class AttributeUsageAttribute : Attribute

13

Các thuộc tính là một loại dữ liệu meta cho các lớp gắn thẻ. Ví dụ, điều này thường được sử dụng trong WinForms để ẩn các điều khiển khỏi thanh công cụ, nhưng có thể được triển khai trong ứng dụng của riêng bạn để cho phép các thể hiện của các lớp khác nhau hành xử theo những cách cụ thể.

Bắt đầu bằng cách tạo một thuộc tính:

[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
public class SortOrderAttribute : Attribute
{
    public int SortOrder { get; set; }

    public SortOrderAttribute(int sortOrder)
    {
        this.SortOrder = sortOrder;
    }
}

Tất cả các lớp thuộc tính phải có hậu tố "Thuộc tính" là hợp lệ.
Sau khi hoàn thành, tạo một lớp sử dụng thuộc tính.

[SortOrder(23)]
public class MyClass
{
    public MyClass()
    {
    }
}

Bây giờ bạn có thể kiểm tra một lớp cụ thể ' SortOrderAttribute(nếu nó có) bằng cách làm như sau:

public class MyInvestigatorClass
{
    public void InvestigateTheAttribute()
    {
        // Get the type object for the class that is using
        // the attribute.
        Type type = typeof(MyClass);

        // Get all custom attributes for the type.
        object[] attributes = type.GetCustomAttributes(
            typeof(SortOrderAttribute), true);

        // Now let's make sure that we got at least one attribute.
        if (attributes != null && attributes.Length > 0)
        {
            // Get the first attribute in the list of custom attributes
            // that is of the type "SortOrderAttribute". This should only
            // be one since we said "AllowMultiple=false".
            SortOrderAttribute attribute = 
                attributes[0] as SortOrderAttribute;

            // Now we can get the sort order for the class "MyClass".
            int sortOrder = attribute.SortOrder;
        }
    }
}

Nếu bạn muốn đọc thêm về điều này, bạn luôn có thể kiểm tra MSDN có mô tả khá hay.
Tôi hy vọng điều này đã giúp bạn ra ngoài!


5

Một thuộc tính là một lớp có chứa một số chức năng mà bạn có thể áp dụng cho các đối tượng trong mã của mình. Để tạo một lớp, hãy tạo một lớp kế thừa từ System.Attribution.

Đối với những gì họ tốt cho ... có những công dụng gần như vô hạn đối với họ.

http://www.codeproject.com/KB/cs/dotnetattribut.aspx


1
"chức năng" là từ sai ở đây; chúng là siêu dữ liệu, không phải chức năng
Marc Gravell

5

Các thuộc tính giống như siêu dữ liệu được áp dụng cho các lớp, phương thức hoặc tập hợp.

Chúng tốt cho bất kỳ số lượng nào (trực quan hóa trình gỡ lỗi, đánh dấu những thứ đã lỗi thời, đánh dấu những thứ là tuần tự hóa, danh sách là vô tận).

Tạo những cái tùy chỉnh của riêng bạn là dễ dàng như chiếc bánh. Bắt đầu ở đây:

http://msdn.microsoft.com/en-us/l Library / sw480ze8 (VS.71) .aspx


5

Trong dự án tôi hiện đang làm việc, có một tập hợp các đối tượng UI có nhiều mùi vị khác nhau và một trình soạn thảo để tập hợp các đối tượng này để tạo các trang để sử dụng trong ứng dụng chính, giống như trình thiết kế biểu mẫu trong DevStudio. Các đối tượng này tồn tại trong tập hợp riêng của chúng và mỗi đối tượng là một lớp xuất phát từ UserControlvà có một thuộc tính tùy chỉnh. Thuộc tính này được định nghĩa như thế này:

[AttributeUsage (AttributeTargets::Class)]
public ref class ControlDescriptionAttribute : Attribute
{
public:
  ControlDescriptionAttribute (String ^name, String ^description) :
    _name (name),
    _description (description)
  {
  }

  property String ^Name
  {
    String ^get () { return _name; }
  }

  property String ^Description
  {
    String ^get () { return _description; }
  }

private:
  String
    ^ _name,
    ^ _description;
};

và tôi áp dụng nó cho một lớp học như thế này:

[ControlDescription ("Pie Chart", "Displays a pie chart")]
public ref class PieControl sealed : UserControl
{
  // stuff
};

đó là những gì các áp phích trước đã nói.

Để sử dụng thuộc tính, trình soạn thảo có Generic::List <Type>chứa các loại điều khiển. Có một hộp danh sách mà người dùng có thể kéo từ và thả vào trang để tạo một thể hiện của điều khiển. Để điền vào hộp danh sách, tôi lấy ControlDescriptionAttributeđiều khiển và điền vào một mục trong danh sách:

// done for each control type
array <Object ^>
  // get all the custom attributes
  ^attributes = controltype->GetCustomAttributes (true);

Type
  // this is the one we're interested in
  ^attributetype = ECMMainPageDisplay::ControlDescriptionAttribute::typeid;

// iterate over the custom attributes
for each (Object ^attribute in attributes)
{
  if (attributetype->IsInstanceOfType (attribute))
  {
    ECMMainPageDisplay::ControlDescriptionAttribute
      ^description = safe_cast <ECMMainPageDisplay::ControlDescriptionAttribute ^> (attribute);

    // get the name and description and create an entry in the list
    ListViewItem
      ^item = gcnew ListViewItem (description->Name);

    item->Tag = controltype->Name;
    item->SubItems->Add (description->Description);

    mcontrols->Items->Add (item);
    break;
  }
}

Lưu ý: ở trên là C ++ / CLI nhưng không khó để chuyển đổi sang C # (vâng, tôi biết, C ++ / CLI là một sự gớm ghiếc nhưng đó là điều tôi phải làm việc với :-()

Bạn có thể đặt các thuộc tính trên hầu hết mọi thứ và có toàn bộ phạm vi của các thuộc tính được xác định trước. Trình chỉnh sửa được đề cập ở trên cũng tìm kiếm các thuộc tính tùy chỉnh trên các thuộc tính mô tả thuộc tính và cách chỉnh sửa nó.

Khi bạn có được toàn bộ ý tưởng, bạn sẽ tự hỏi làm thế nào bạn sống mà không có chúng.


4

Như đã nói, các thuộc tính tương đối dễ dàng để tạo ra. Phần khác của công việc là tạo mã sử dụng nó. Trong hầu hết các trường hợp, bạn sẽ sử dụng sự phản chiếu trong thời gian chạy để thay đổi hành vi dựa trên sự hiện diện của một thuộc tính hoặc thuộc tính của nó. Cũng có những kịch bản mà bạn sẽ kiểm tra các thuộc tính trên mã được biên dịch để thực hiện một số loại phân tích tĩnh. Ví dụ: các tham số có thể được đánh dấu là không null và công cụ phân tích có thể sử dụng điều này như một gợi ý.

Sử dụng các thuộc tính và biết các kịch bản phù hợp cho việc sử dụng chúng là phần lớn công việc.


3

Về cơ bản, các thuộc tính là các bit dữ liệu bạn muốn đính kèm vào các loại của mình (các lớp, phương thức, sự kiện, enum, v.v.)

Ý tưởng là trong thời gian chạy, một số loại / khung / công cụ khác sẽ truy vấn loại của bạn để biết thông tin trong thuộc tính và hành động theo nó.

Vì vậy, ví dụ, Visual Studio có thể truy vấn các thuộc tính trên điều khiển của bên thứ 3 để tìm ra thuộc tính nào của điều khiển sẽ xuất hiện trong ngăn Thuộc tính tại thời điểm thiết kế.

Các thuộc tính cũng có thể được sử dụng trong Lập trình hướng đối tượng để tiêm / thao tác các đối tượng trong thời gian chạy dựa trên các thuộc tính trang trí chúng và thêm xác nhận, ghi nhật ký, v.v. vào các đối tượng mà không ảnh hưởng đến logic nghiệp vụ của đối tượng.


2

Bạn có thể sử dụng các thuộc tính tùy chỉnh như một cách đơn giản để xác định các giá trị thẻ trong các lớp con mà không phải viết cùng một mã nhiều lần cho mỗi lớp con. Tôi đã bắt gặp một ví dụ ngắn gọn súc tích của John Waters về cách xác định và sử dụng các thuộc tính tùy chỉnh trong mã của riêng bạn.

Có một hướng dẫn tại http://msdn.microsoft.com/en-us/l Library / aa288454 (VS.71) .aspx


2

Để bắt đầu tạo thuộc tính, hãy mở tệp nguồn C #, nhập attributevà nhấn [TAB]. Nó sẽ mở rộng thành một mẫu cho một thuộc tính mới.


6
Làm thế nào để nó trả lời câu hỏi? nó nên là một bình luận, không phải là một câu trả lời
gdoron đang hỗ trợ Monica

1

Các thuộc tính cũng thường được sử dụng cho lập trình hướng theo khía cạnh. Để biết ví dụ về điều này, hãy xem dự án PostSharp .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.