C # 'da özel bir özellik nasıl oluşturulur?


119

Pek çok kez denedim, ancak yine de özel özelliklerin kullanımını anlayamıyorum (zaten birçok bağlantıdan geçtim).

Herhangi biri bana kodlu özel bir özniteliğin çok basit bir örneğini açıklayabilir mi?

Yanıtlar:


96

Özel bir Öznitelik oluşturma kodu oldukça basit olsa da, özniteliklerin ne olduğunu anlamanız çok önemlidir:

Öznitelikler, programınızda derlenen meta verilerdir. Özniteliklerin kendileri bir sınıfa, özelliğe veya modüle herhangi bir işlevsellik eklemez - yalnızca veri. Bununla birlikte, yansıma kullanarak, işlevsellik oluşturmak için bu niteliklerden yararlanılabilir.

Öyleyse, örneğin, Microsoft Enterprise Library'den Validation Application Block'a bakalım . Bir kod örneğine bakarsanız şunları görürsünüz:

    /// <summary>
    /// blah blah code.
    /// </summary>
    [DataMember]
    [StringLengthValidator(8, RangeBoundaryType.Inclusive, 8, RangeBoundaryType.Inclusive, MessageTemplate = "\"{1}\" must always have \"{4}\" characters.")]
    public string Code { get; set; }

Yukarıdaki kod parçasından, her değiştirildiğinde, Doğrulayıcı kurallarına göre kodun her zaman doğrulanacağı tahmin edilebilir (örnekte, en az 8 karakter ve en fazla 8 karakter vardır). Ancak gerçek şu ki, Öznitelik hiçbir şey yapmaz; daha önce belirtildiği gibi, mülke yalnızca meta verileri ekler.

Bununla birlikte, Enterprise Library Validation.Validatenesnenize bakacak bir yönteme sahiptir ve her özellik için, içeriğin öznitelik tarafından bildirilen kuralı ihlal edip etmediğini kontrol eder.

Yani, öznitelikler hakkında böyle düşünmelisiniz - daha sonra diğer yöntemler / sınıflar / vb. Tarafından kullanılabilecek verileri kodunuza eklemenin bir yolu.


cevabı gerçekten beğenecek miyim ve özellikle ", bir soru daha yukarıdaki kodun küme ifadesine aynı koşulu koyabilirim, böylece niteliklerden ne kadar farklı,
slash shogdhe

1
@slash: Bunu yeniden ifade edebilir misiniz? Soruyu tam olarak anlamadım.
Bruno Brant

1
Eğik çizgi, nitelikleri kullanmakla gerçek doğrulama kodunu özellik belirleyiciye koymak arasındaki farkı sormak anlamına geliyordu. Cevap: Değerin doğrulanması için ayarlayıcı içerisine kod yazılabilirken, özniteliklerin tek başına kullanılması doğrulama işlemini gerçekleştirmeyecektir. Öznitelikler yalnızca "meta verilerdir". Başka bir yerdeki başka bir kod, kullandığınız özniteliklerle ilgilenmeli, onları okumalı ve bunlara göre eylemler gerçekleştirmelidir. Tipik bir örnek, @BrunoBrant'ın bahsettiği gibi bir doğrulama kitaplığıdır.
romar

10
Bunun neden kabul edilen cevap olduğundan emin değilim. Asıl soru (Google'da da dizine eklenmiştir) " C #'da özel bir öznitelik nasıl oluşturulur ". Cevaplar bu konuya hiç girmiyor. Öte yandan 2. cevap var.
Drakestar

İkinci cevabın daha çok soruyla ilgili olduğunu düşünüyorum.
Mohammad Taherian

267

Öznitelikten türetilen bir sınıf yazarak başlarsınız :

public class MyCustomAttribute: Attribute
{
    public string SomeProperty { get; set; }
}

Daha sonra bu nitelikle her şeyi (sınıf, yöntem, özellik, ...) dekore edebilirsiniz:

[MyCustomAttribute(SomeProperty = "foo bar")]
public class Foo
{

}

ve nihayet onu getirmek için yansıma kullanırsınız:

var customAttributes = (MyCustomAttribute[])typeof(Foo).GetCustomAttributes(typeof(MyCustomAttribute), true);
if (customAttributes.Length > 0)
{
    var myAttribute = customAttributes[0];
    string value = myAttribute.SomeProperty;
    // TODO: Do something with the value
}

AttributeUsage özelliğini kullanarak bu özel özelliğin uygulanabileceği hedef türlerini sınırlayabilirsiniz :

/// <summary>
/// This attribute can only be applied to classes
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class MyCustomAttribute : Attribute

Öznitelikler hakkında bilinmesi gereken önemli şeyler:

  • Nitelikler meta verilerdir.
  • Derleme sırasında derleme sırasında pişirilirler, bu da özelliklerini nasıl ayarlayabileceğiniz konusunda çok ciddi sonuçları vardır. Yalnızca sabit (derleme zamanında bilinen) değerler kabul edilir
  • Özel öznitelikleri anlamanın ve kullanmanın tek yolu Yansıma kullanmaktır . Dolayısıyla, çalışma zamanında onları almak ve özel bir öznitelikle bir şeyi süslemek için yansıma kullanmazsanız, çok fazla şey olmasını beklemeyin.
  • Niteliklerin yaratılma zamanı deterministik değildir. CLR tarafından somutlaştırılırlar ve onun üzerinde kesinlikle hiçbir kontrolünüz yoktur.

3
Nerede, hangi işlev / sınıfta, onu getirmek için yansıma kullanmalıyım?
Hasan A Yousef

@Hasan A Yousef, örneğin Entity Framework'te çerçeveye şunu söyleyen "Key" özniteliği vardır: Bu özellik Birincil Anahtar olarak değerlendirilmelidir. ORM'yi oluştururken nitelikler çok faydalıdır
Parsa

Bir sınıfta değil, bir mülkte özel bir özniteliğe nasıl erişirsiniz?
Canvas


Jenerik var value = typeof(Foo).GetCustomAttributes<MyCustomAttribute>().First().SomeProperty;
ilaçlarla

27

Darin Dimitrov'un harika yanıtını kullanarak / kopyalayarak , bir sınıfta değil, bir mülkte özel bir özelliğe nasıl erişilir:

Dekore edilmiş mülk [sınıfın Foo]:

[MyCustomAttribute(SomeProperty = "This is a custom property")]
public string MyProperty { get; set; }

Getiriliyor:

PropertyInfo propertyInfo = typeof(Foo).GetProperty(propertyToCheck);
object[] attribute = propertyInfo.GetCustomAttributes(typeof(MyCustomAttribute), true);
if (attribute.Length > 0)
{
    MyCustomAttribute myAttribute = (MyCustomAttribute)attribute[0];
    string propertyValue = myAttribute.SomeProperty;
}

Sen bu özel özellik erişmek için bir döngü ve kullanım yansımada bu atabilir her sınıfın özellik Foosıra,:

foreach (PropertyInfo propertyInfo in Foo.GetType().GetProperties())
{
    string propertyName = propertyInfo.Name;

    object[] attribute = propertyInfo.GetCustomAttributes(typeof(MyCustomAttribute), true);
    // Just in case you have a property without this annotation
    if (attribute.Length > 0)
    {
        MyCustomAttribute myAttribute = (MyCustomAttribute)attribute[0];
        string propertyValue = myAttribute.SomeProperty;
        // TODO: whatever you need with this propertyValue
    }
}

Sayende büyük teşekkürler, Darin !!


Bir mülkte hangi tür niteliklerin bulunduğunu bilmiyorsak bunu nasıl uzatabiliriz? object[] attribute = propertyInfo.GetCustomAttributes(typeof(???), true);Ben sadece hepsini yinelemek ve m1()bilinmeyen her özniteliğin bir yöntemini çağırmak istiyorum
heyNow

0

Kısa cevap, c # 'da bir öznitelik oluşturmak içindir, onu yalnızca Öznitelik sınıfından devralmanız gerekir, Sadece bu :)

Ancak burada özellikleri ayrıntılı olarak açıklayacağım:

temelde öznitelikler, mantığımızı derlemelere, sınıflara, yöntemlere, özelliklere, alanlara, ... uygulamak için kullanabileceğimiz sınıflardır.

.Net'te Microsoft, ([Gerekli], [StringLength (100)], [Range (0, 999.99)]) gibi Eski veya Doğrulama Öznitelikleri gibi önceden tanımlanmış Öznitelikler sağlamıştır, ayrıca asp.net'te ActionFilters gibi özniteliklere sahibiz. İstediğimiz mantığı kodlarımıza uygulamak için çok yararlı olabilir ( öğrenmek için tutkuluysanız, eylem filtreleri hakkındaki bu makaleyi okuyun )

Bir başka nokta, AttibuteUsage aracılığıyla özniteliğinize bir tür yapılandırma uygulayabilirsiniz.

  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]

AttributeUsage ile bir öznitelik sınıfını dekore ettiğinizde, c # derleyicisine bu özniteliği nerede kullanacağımı söyleyebilirsiniz: Bunu sınıflarda, özelliklerdeki derlemelerde veya üzerinde kullanacağım ... ve özniteliğimin kullanımına izin verilir tanımlanmış hedefler üzerinde (sınıflar, derlemeler, özellikler, ...) birkaç kez mi ?!

Niteliklerle ilgili bu tanımdan sonra size bir örnek göstereceğim: Üniversitede yeni bir ders tanımlamak istediğimizi ve üniversitemizdeki yöneticilerin ve yüksek lisansların yeni bir Ders tanımlamasına izin vermek istediğimizi hayal edin, tamam mı?

namespace ConsoleApp1
{
    /// <summary>
    /// All Roles in our scenario
    /// </summary>
    public enum UniversityRoles
    {
        Admin,
        Master,
        Employee,
        Student
    }

    /// <summary>
    /// This attribute will check the Max Length of Properties/fields
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]
    public class ValidRoleForAccess : Attribute
    {
        public ValidRoleForAccess(UniversityRoles role)
        {
            Role = role;
        }
        public UniversityRoles Role { get; private set; }

    }


    /// <summary>
    /// we suppose that just admins and masters can define new Lesson
    /// </summary>
    [ValidRoleForAccess(UniversityRoles.Admin)]
    [ValidRoleForAccess(UniversityRoles.Master)]
    public class Lesson
    {
        public Lesson(int id, string name, DateTime startTime, User owner)
        {
            var lessType = typeof(Lesson);
            var validRolesForAccesses = lessType.GetCustomAttributes<ValidRoleForAccess>();

            if (validRolesForAccesses.All(x => x.Role.ToString() != owner.GetType().Name))
            {
                throw new Exception("You are not Allowed to define a new lesson");
            }
            
            Id = id;
            Name = name;
            StartTime = startTime;
            Owner = owner;
        }
        public int Id { get; private set; }
        public string Name { get; private set; }
        public DateTime StartTime { get; private set; }

        /// <summary>
        /// Owner is some one who define the lesson in university website
        /// </summary>
        public User Owner { get; private set; }

    }

    public abstract class User
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public DateTime DateOfBirth { get; set; }
    }


    public class Master : User
    {
        public DateTime HireDate { get; set; }
        public Decimal Salary { get; set; }
        public string Department { get; set; }
    }

    public class Student : User
    {
        public float GPA { get; set; }
    }



    class Program
    {
        static void Main(string[] args)
        {

            #region  exampl1

            var master = new Master()
            {
                Name = "Hamid Hasani",
                Id = 1,
                DateOfBirth = new DateTime(1994, 8, 15),
                Department = "Computer Engineering",
                HireDate = new DateTime(2018, 1, 1),
                Salary = 10000
            };
            var math = new Lesson(1, "Math", DateTime.Today, master);

            #endregion

            #region exampl2
            var student = new Student()
            {
                Name = "Hamid Hasani",
                Id = 1,
                DateOfBirth = new DateTime(1994, 8, 15),
                GPA = 16
            };
            var literature = new Lesson(2, "literature", DateTime.Now.AddDays(7), student);
            #endregion

            ReadLine();
        }
    }


}

Gerçek programlama dünyasında belki bu yaklaşımı öznitelikleri kullanmak için kullanmayız ve bunu öznitelikleri kullanmadaki eğitimsel noktası nedeniyle söyledim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.