C# 如何在C中创建自定义属性#

C# 如何在C中创建自定义属性#,c#,c#-4.0,custom-attributes,C#,C# 4.0,Custom Attributes,我尝试了很多次,但仍然无法理解自定义属性的用法(我已经浏览了很多链接) 有人能给我解释一下自定义属性的一个非常基本的示例吗?您首先要编写一个派生自以下内容的类: 然后您可以使用此属性装饰任何内容(类、方法、属性等): [MyCustomAttribute(SomeProperty = "foo bar")] public class Foo { } /// <summary> /// This attribute can only be applied to classes //

我尝试了很多次,但仍然无法理解自定义属性的用法(我已经浏览了很多链接)


有人能给我解释一下自定义属性的一个非常基本的示例吗?

您首先要编写一个派生自以下内容的类:

然后您可以使用此属性装饰任何内容(类、方法、属性等):

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

}
/// <summary>
/// This attribute can only be applied to classes
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class MyCustomAttribute : Attribute
最后,您将使用反射来获取它:

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
}
您可以使用属性限制此自定义属性可应用到的目标类型:

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

}
/// <summary>
/// This attribute can only be applied to classes
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class MyCustomAttribute : Attribute
//
///此属性只能应用于类
/// 
[AttributeUsage(AttributeTargets.Class)]
公共类MyCustomAttribute:属性
关于属性需要了解的重要事项:

  • 属性是元数据
  • 它们在编译时被烘焙到程序集中,这对如何设置它们的属性有着非常严重的影响。只接受常量(编译时已知)值
  • 理解和使用自定义属性的唯一方法是使用。因此,如果您在运行时不使用反射来获取它们并用自定义属性装饰某些东西,那么就不要期望发生太多事情
  • 属性的创建时间是不确定的。它们由CLR实例化,您完全无法控制它

虽然创建自定义的代码相当简单,但了解哪些属性非常重要:

属性是编译到程序中的元数据。属性本身不向类、属性或模块添加任何功能,只添加数据。但是,使用反射,可以利用这些属性来创建功能

举个例子,让我们看看微软的。如果查看代码示例,您将看到:

    /// <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; }
//
///胡说八道的代码。
/// 
[数据成员]
[StringLengthValidator(8,RangeBoundaryType.Inclusive,8,RangeBoundaryType.Inclusive,MessageTemplate=“\”{1}\”必须始终包含\“{4}\”个字符。“)]
公共字符串代码{get;set;}
从上面的代码片段中,人们可能会猜测,代码总是会根据验证器的规则进行验证(在本例中,至少有8个字符,最多有8个字符)。但事实是,属性不起任何作用;如前所述,它只向属性添加元数据

但是,企业库有一个
Validation.Validate
方法,该方法将查看对象,对于每个属性,它将检查内容是否违反属性通知的规则

因此,这就是您应该如何考虑属性的方法--一种向代码中添加数据的方法,以后可能会被其他方法/类等使用。

利用/复制,这是如何访问属性而不是类上的自定义属性:

[class
Foo
]的修饰属性:

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

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;
}
您可以将其放入循环中,并使用反射来访问类
Foo
的每个属性上的此自定义属性:

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

少校谢谢你,达林

简单的答案是在c中创建属性#您只需要从属性类继承它,如下所示:)

但在这里,我将详细解释属性:

基本上,属性是我们可以使用它们将逻辑应用于程序集、类、方法、属性、字段等的类

在.Net中,Microsoft提供了一些预定义属性,如过时属性或验证属性,如([Required]、[StringLength(100)]、[Range(0999.99)],并且我们在asp.Net中提供了一些属性,如ActionFilters,这些属性对于将所需逻辑应用于代码非常有用(如果你热衷于学习,请阅读有关动作过滤器的文章)

还有一点,您可以通过AttibuteUsage对属性应用某种配置

  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]
当您使用AttributeUsage装饰属性类时,您可以告诉c#编译器我将在何处使用此属性:我将在类、属性上的程序集或…上使用此属性,并且允许我的属性在定义的目标(类、程序集、属性等)上使用多次

在定义了属性之后,我将向您展示一个示例: 想象一下,我们想在大学里定义一门新课,我们想让我们大学里的管理员和硕士来定义一门新课,好吗

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


}
名称空间控制台EAPP1
{
/// 
///我们场景中的所有角色
/// 
公立大学
{
管理
大师,
雇员,,
学生
}
/// 
///此属性将检查属性/字段的最大长度
/// 
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct,AllowMultiple=true)]
公共类ValidRoleForAccess:属性
{
公共ValidRoleForAccess(大学角色)
{
角色=角色;
}
公立大学角色{get;private set;}
}
/// 
///我们认为只有管理员和大师才能定义新课程
/// 
[ValidRoleForAccess(大学管理)]
[有效期(大学硕士)]
公共课
{
公共课程(int-id、字符串名称、日期时间开始时间、用户所有者)
{
var lessType=typeof(课程);
var validrolesforaccess=lessype.GetCustomAttributes();
if(validRoleForAccess.All(x=>x.Role.ToString()!=owner.GetType().Name))
{
抛出新异常(“不允许定义新课程”);
}
Id=Id;
名称=名称;
开始时间=开始时间;
所有者=所有者;
}
public int Id{get;private set;}
公共字符串名称{get;private set;}
公共日期时间标准