Apa atribut dalam .NET?

206

Apa itu atribut di .NET, untuk apa atributnya, dan bagaimana cara membuat atribut saya sendiri?

Corey
sumber

Jawaban:

146

Metadata. Data tentang objek / metode / properti Anda.

Sebagai contoh, saya dapat mendeklarasikan atribut yang disebut: DisplayOrder sehingga saya dapat dengan mudah mengontrol properti urutan apa yang akan muncul di UI. Saya kemudian dapat menambahkannya ke kelas dan menulis beberapa komponen GUI yang mengekstrak atribut dan memesan elemen UI dengan tepat.

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

Dengan demikian memastikan bahwa SomeInt selalu ditampilkan sebelum SomeDate ketika bekerja dengan komponen GUI khusus saya.

Namun, Anda akan melihatnya paling sering digunakan di luar lingkungan pengkodean langsung. Misalnya Desainer Windows menggunakannya secara luas sehingga ia tahu cara menangani objek yang dibuat khusus. Menggunakan BrowsableAttribute seperti:

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

Memberitahu desainer untuk tidak mencantumkan ini di properti yang tersedia di jendela Properties pada waktu desain misalnya.

Anda juga bisa menggunakannya untuk operasi pembuatan kode, pra-kompilasi (seperti Pasca-Tajam) atau operasi run-time seperti Reflection.Emit. Misalnya, Anda dapat menulis sedikit kode untuk pembuatan profil yang secara transparan membungkus setiap panggilan yang dilakukan oleh kode Anda dan dikalikan dengan waktu. Anda bisa "menyisih" dari penentuan waktu melalui atribut yang Anda tempatkan pada metode tertentu.

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

Mendeklarasikannya itu mudah, cukup buat kelas yang mewarisi dari Atribut.

public class DisplayOrderAttribute : Attribute
{
    private int order;

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

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

Dan ingat bahwa ketika Anda menggunakan atribut Anda dapat menghilangkan suffix "atribut" kompiler akan menambahkannya untuk Anda.

CATATAN: Atribut tidak melakukan apa pun sendiri - perlu ada beberapa kode lain yang menggunakannya. Terkadang kode itu telah ditulis untuk Anda tetapi kadang-kadang Anda harus menulisnya sendiri. Sebagai contoh, kompiler C # peduli tentang beberapa dan kerangka kerja tertentu menggunakan beberapa kerangka kerja (mis. NUnit mencari [TestFixture] pada suatu kelas dan [Uji] pada metode pengujian saat memuat sebuah rakitan).
Jadi, ketika membuat atribut khusus Anda sendiri, ketahuilah bahwa itu tidak akan memengaruhi perilaku kode Anda sama sekali. Anda harus menulis bagian lain yang memeriksa atribut (melalui refleksi) dan menindaklanjutinya.

Berdalih
sumber
32
Untuk apa nilainya, ini adalah daftar semua (
bawaan
1
Bagaimana Anda menggunakan "SomeProfilingMethod" Anda sebagai atribut?
Ray Tanpa Cinta
@RayLoveless itu bukan atribut, SomeProfilingMethod adalah kode instrumentasi yang mencari atribut profil. Khususnya dalam contoh saya memberikan mencari atribut "opt-out" (NoTimingAttribute) sebagai lawan dari atribut "opt-in". Idenya adalah bahwa itu kali segalanya.
Quibblesome
@ Quibblesome dapatkah Anda menambahkan sesuatu seperti "Atribut tidak melakukan apa pun dengan sendirinya - perlu ada beberapa kode lain untuk menggunakannya (kompiler peduli tentang pasangan, beberapa kerangka kerja menggunakan beberapa). Hanya membuat atribut tidak akan memengaruhi perilaku kode - Anda perlu menulis bagian lain yang memeriksa atribut (melalui refleksi) dan menindaklanjutinya ". (atau saya bisa melakukannya jika Anda ok). Banyak orang mengharapkan atribut berfungsi secara ajaib dan tidak ada jawaban di sini yang menjelaskan hal itu. (atau hanya tautan ke stackoverflow.com/questions/4879521/… yang
meliputnya
hanya jika Anda berhenti menggunakan Bing. Tidak j / k Saya menggunakan DuckDuckGo sebagai utama saya yang terutama menggunakan Bing iirc. :)
Quibblesome
36

Banyak orang telah menjawab tetapi belum ada yang menyebutkan ini sejauh ini ...

Atribut banyak digunakan dengan refleksi. Refleksi sudah cukup lambat.

Sangat berharga menandai atribut kustom Anda sebagaisealed kelas untuk meningkatkan kinerja runtime mereka.

Ini juga merupakan ide yang baik untuk mempertimbangkan di mana tempat yang tepat untuk menggunakan atribut seperti itu, dan untuk atribut atribut Anda (!) Untuk menunjukkan ini melalui AttributeUsage. Daftar penggunaan atribut yang tersedia mungkin mengejutkan Anda:

  • Majelis
  • Modul
  • Kelas
  • Struct
  • Enum
  • Konstruktor
  • metode
  • Properti
  • Bidang
  • Peristiwa
  • Antarmuka
  • Parameter
  • Melimpahkan
  • Pengembalian Nilai
  • GenericParameter
  • Semua

Itu juga keren bahwa atribut AttributeUsage adalah bagian dari tanda tangan atribut AttributeUsage. Whoa untuk dependensi melingkar!

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

Atribut adalah sejenis data meta untuk kelas penandaan. Ini sering digunakan dalam WinForms misalnya untuk menyembunyikan kontrol dari toolbar, tetapi dapat diimplementasikan dalam aplikasi Anda sendiri untuk memungkinkan instance dari kelas yang berbeda untuk berperilaku dengan cara tertentu.

Mulai dengan membuat atribut:

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

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

Semua kelas atribut harus memiliki akhiran "Atribut" agar valid.
Setelah ini selesai, buat kelas yang menggunakan atribut.

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

Sekarang Anda dapat memeriksa kelas tertentu ' SortOrderAttribute(jika ada) dengan melakukan hal berikut:

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

Jika Anda ingin membaca lebih lanjut tentang ini, Anda selalu dapat memeriksa MSDN yang memiliki deskripsi yang cukup bagus.
Saya harap ini membantu Anda!

Patrik Svensson
sumber
5

Atribut adalah kelas yang berisi sedikit fungsionalitas yang dapat Anda terapkan ke objek dalam kode Anda. Untuk membuatnya, buat kelas yang mewarisi dari System.Attribute.

Adapun apa yang mereka baik untuk ... ada kegunaan yang hampir tak terbatas untuk mereka.

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

TheSmurf
sumber
1
"fungsionalitas" adalah kata yang salah di sini; mereka adalah metadata, bukan fungsionalitas
Marc Gravell
5

Atribut seperti metadata yang diterapkan pada kelas, metode, atau rakitan.

Mereka baik untuk sejumlah hal (visualisasi debugger, menandai hal-hal sebagai usang, menandai hal-hal sebagai serializable, daftarnya tidak ada habisnya).

Membuat yang Anda kustom sendiri semudah pie. Mulai di sini:

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

Stu
sumber
5

Dalam proyek yang sedang saya kerjakan, ada satu set objek UI dari berbagai rasa dan editor untuk merakit objek-objek ini untuk membuat halaman untuk digunakan dalam aplikasi utama, sedikit seperti perancang formulir di DevStudio. Objek-objek ini ada dalam rakitan mereka sendiri dan setiap objek adalah kelas yang berasal dari UserControldan memiliki atribut khusus. Atribut ini didefinisikan seperti ini:

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

dan saya menerapkannya ke kelas seperti ini:

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

itulah yang dikatakan oleh poster sebelumnya.

Untuk menggunakan atribut, editor memiliki Generic::List <Type>tipe kontrol yang berisi. Ada kotak daftar di mana pengguna dapat menarik dari dan menjatuhkan ke halaman untuk membuat turunan kontrol. Untuk mengisi kotak daftar, saya mendapatkan ControlDescriptionAttributeuntuk kontrol dan mengisi entri dalam daftar:

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

Catatan: di atas adalah C ++ / CLI tetapi tidak sulit untuk mengkonversi ke C # (yeah, saya tahu, C ++ / CLI adalah kekejian tapi itu yang harus saya kerjakan dengan :-()

Anda dapat menempatkan atribut pada sebagian besar hal dan ada berbagai macam atribut yang telah ditentukan. Editor yang disebutkan di atas juga mencari atribut khusus pada properti yang menggambarkan properti dan cara mengeditnya.

Setelah Anda mendapatkan seluruh ide, Anda akan bertanya-tanya bagaimana Anda bisa hidup tanpanya.

Mendesis
sumber
4

Seperti yang dikatakan, Atribut relatif mudah dibuat. Bagian lain dari karya ini adalah membuat kode yang menggunakannya. Dalam kebanyakan kasus, Anda akan menggunakan refleksi pada saat runtime untuk mengubah perilaku berdasarkan keberadaan atribut atau propertinya. Ada juga skenario di mana Anda akan memeriksa atribut pada kode yang dikompilasi untuk melakukan semacam analisis statis. Misalnya, parameter mungkin ditandai sebagai bukan nol dan alat analisis dapat menggunakan ini sebagai petunjuk.

Menggunakan atribut dan mengetahui skenario yang sesuai untuk penggunaannya adalah sebagian besar pekerjaan.

denis phillips
sumber
3

Atribut pada dasarnya adalah bit data yang ingin Anda lampirkan ke tipe Anda (kelas, metode, peristiwa, enum, dll.)

Idenya adalah bahwa pada saat dijalankan beberapa jenis / kerangka / alat lain akan meminta Anda tipe untuk informasi dalam atribut dan menindaklanjutinya.

Jadi, misalnya, Visual Studio dapat meminta atribut pada kontrol pihak ke-3 untuk mencari tahu properti kontrol mana yang akan muncul di panel Properties pada waktu desain.

Atribut juga dapat digunakan dalam Pemrograman Berorientasi Aspek untuk menyuntikkan / memanipulasi objek pada waktu berjalan berdasarkan atribut yang menghiasinya dan menambahkan validasi, pencatatan, dll. Ke objek tanpa mempengaruhi logika bisnis objek.

urini
sumber
2

Untuk mulai membuat atribut, buka file sumber C #, ketik attributedan tekan [TAB]. Ini akan diperluas ke templat untuk atribut baru.

Jay Bazuzi
sumber
6
Bagaimana cara menjawab pertanyaan? itu harus berupa komentar, bukan jawaban.
gdoron mendukung Monica
1

Atribut juga biasa digunakan untuk Pemrograman Berorientasi Aspek. Untuk contoh ini, periksa proyek PostSharp .

Josh G
sumber