C# 精通之路 —— .NET Framework最具创意 —> 定制特性,这些细节知识你知多少?

在这里插入图片描述
作者:浪子花梦,一个有趣的程序员 ~
此文章将讲解 .net 上面一个非常有用的技术 —— 定制特性,学习源于《CLR via C#》,菜鸟教程 . . .


文章目录


定制特性介绍与简单使用

我在以前的学习中就接触过了定制特性,当时只知道抄代码,根本不知道它是什么意思,在如下两篇文章中就有所遇到过:
1)C# 之 鼠标点击进程 —— 截取图片
2)C# 精通之路 —— 基本类型杂项详解(StringBuilder、枚举位标志、下限非0的数组),这些细节知识你知多少?

我们可以通过定制特性给我们现成的类添加额外的辅助,例如我上次在位标志相关文章中写过一个叫 [Flags] 的特性,这个特性重写了枚举中的 ToString方法,使它以字符串的形式输出数据,如下所示:
在这里插入图片描述

Obsolete 定制特性

下面我们来介绍一下一个叫 [Obsolete] 的特性,当我们想把一个类中的方法放弃,但又不想把它删除时,这个特性就派上用处了,Obsolete 定制特性有两个必需的定位参数:
在这里插入图片描述
下面的代码将演示这种特性的使用方式:

using System;
public class MyClass
{
	[Obsolete("Don't use OldMethod, use NewMethod instead", true)]
   	static void OldMethod()
   	{
	 	Console.WriteLine("It is the old method");
   	}
    static void NewMethod()
    {
	 	Console.WriteLine("It is the new method");
    }
    
    public static void Main()
    {
 		OldMethod();
    }
}

运行程序我们将发生下面这种情况:
在这里插入图片描述
这个方法已经过时了,并且显示我们自定义的消息:

Don’t use OldMethod, use NewMethod instead

当我们把第二个定位参数改为 false时,编译器将发出警告,但程序是可以编译通过的:
在这里插入图片描述

.NET Framework 为我们准备了大量的定制特性,有兴趣的小伙伴可以自己查看文档 . . .

.
.
.


自定义定制特性(示例讲解)

下面我们将通过一个示例来讲解一个定制特性是怎么写出来的 . . .

定制特性定义

定制的特性类需要从 Attribute 类派生,如下所示我们定义一个从 Attribute派生的类,这个类的里面有三个字段,分别是:sayHello,sayLoveyou,name,并且我们在构造器中对他们进行了初始化:

public class WelcomeInfoAttribute: System.Attribute
{
    private String sayHello;
    private String sayLoveyou;
    private String name;

    public WelcomeInfo(String name, String hello, String love)
    {
		this.name = name;
 		this.sayHello = hello;
	 	this.sayLoveyou = love;
    }

    public String SayHello
    {
        get { return sayHello; }
    }

    public String SayLoveyou
    {
        get { return sayLoveyou; }
    }

    public String Name
    {
        get { return name; }
    }

}

当前,我们不可能让定制特性去随意的使用,我们可以使用 [AttributeUsage] 去限制我们自己的自定义特性,让我们的特性只限制针对类,或者方法等等成员,也可以限制这个特性是否可以重复使用,或者在基类上面使用这个特性,派生类是否限制住不使用这个特性,原型如下所示:
在这里插入图片描述
现在我们来使用这个特性,用于限制我们的自定义定制特性,使用方法如下所示:
在这里插入图片描述
我们将这个特性应用在类或者方法中,并且可以重复使用,不允许有基类派生到子类中 . . .

.

定制特性使用

我们的定制特性准备好了,现在让我们来试试怎么用吧 . . .

我们定义一个People类,其中只有一个方法,特性使用如下所示:
在这里插入图片描述
我们在类和方法上面,分别使用了两次特性,特性的使用方法就是这么简单 . . .

.

定制特性访问 > 反射基础

我们现在需要做的,就是通过这个 People类 来访问到我们自己的定制特性中的信息 . . .

要想访问的话,我们先来看一下 CustomAttributeExtensions 这个类,这个类中定义了三个方法,这三个方法又有许多种重载的版本,如下所示:

1)GetCustomAttribute:
在这里插入图片描述

2)GetCustomAttributes:
在这里插入图片描述
3)IsDefined:在这里插入图片描述

我们这个示例只用到了 GetCustomAttributes 方法,即获取当前此类型中的所有特性类,主函数测试代码如下所示:

public static void Main()
{
    People people = new People();
    people.SayHello();

    Type type = people.GetType();

    foreach (var p in type.GetCustomAttributes(false))
    {
        WelcomeInfo welcome = (WelcomeInfo)p;

        if (welcome != null)    // 此特性应用在类上 
        {
            Console.WriteLine("Name: " + welcome.Name);
            Console.WriteLine("SayHello: " + welcome.SayHello);
            Console.WriteLine("SayLoveyou: " + welcome.SayLoveyou);
            Console.WriteLine();
        }
    }

    Console.WriteLine();
    Console.WriteLine();

    foreach (var p in type.GetMethods())        // 获取这个类的所有方法,这个类只有一个方法
    {
        foreach (var item in p.GetCustomAttributes(false))
        {
            WelcomeInfo welcome;
            try { welcome = (WelcomeInfo)item; }
            catch { break; }

            if (welcome != null)    // 此特性应用在方法上面 
            {
                Console.WriteLine("Name: " + welcome.Name);
                Console.WriteLine("SayHello: " + welcome.SayHello);
                Console.WriteLine("SayLoveyou: " + welcome.SayLoveyou);
                Console.WriteLine();
            }
        }
    }

    Console.ReadKey();
}

输出的结果如下所示:
在这里插入图片描述

.
.
.


猜你喜欢

转载自blog.csdn.net/weixin_42100963/article/details/107504656