#define USE_FUN
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Lesson22_Attribute
{
#region 一、特性是什么
// 特性本质是一个类
// 我们可用使用特性 为元数据添加额外信息
// 比如一个类、成员变量、成员方法等 为他们添加更多的额外信息
// 之后通过反射 来获取这些 额外的信息
#endregion
#region 自定义特性
// 继承特性基类
class MyCustomAttribute: Attribute
{
// 特性中的成员变量
public string info;
public MyCustomAttribute(string info)
{
this.info = info;
}
public void AttributeFun()
{
Console.WriteLine("特性中的方法");
}
}
#endregion
#region 三、特性的使用
// [特性名(参数列表)]
// 本质上就是调用 特性的构造函数
// 写在 类,函数,变量的上一行。
[MyCustom("类的特性 -- 特性自定义类 ")]
class MyClass
{
[MyCustom("特性成员变量")]
public int Value;
[MyCustom("特性测试函数")]
public void TestFun([MyCustom("函数参数")]int a)
{
}
}
#endregion
#region 四、限制特性的使用范围
// 特性类上添加 特性 可用限制其使用范围
// AttributeTargets 特性使用范围
// AllowMultiple 一个对象 多次叠加特性
// Inherited 允许继承
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple =true, Inherited =true)]
class MyCustom2Attribute : Attribute
{
}
#endregion
#region 五、系统自带特性 -- 过时特性
// 过时特性
// obsolete
// 提示用户 使用的方法或成员已经过时,使用新的方法
// 一般加在 函数前面
class TestClass
{
// false 警告, true 调用报错
[Obsolete("OldSpeek 方法已经过时,请使用Speek", false)]
public void OldSpeek(string str)
{
Console.WriteLine(str);
}
public void Speek()
{
}
public void SpeekCaller(string str,
[CallerFilePath]string fileName="",
[CallerLineNumber]int line = 0,
[CallerMemberName]string target="")
{
string baseName = Path.GetFileName(fileName);
Console.WriteLine(str);
Console.WriteLine("调用文件:" + baseName);
Console.WriteLine("调用行数:" + line.ToString());
Console.WriteLine("调用函数:" + target);
}
}
#endregion
#region 六、系统自带特性--调用者信息特性
// CallerFilePath 特性 -- 那个文件调用
// CallerLineNumber 特性 -- 那个一行调用
// CallerMemberName 特性 -- 那个函数调用
// 命名空间 using System.Runtime.CompilerServices;
// 函数参数的特性
#endregion
#region 七、系统自带特性 -- 条件编译特性
// 条件编译特性
// Conditional
// 主要在调试代码上使用
// 命名空间 using System.Diagnostics;
#endregion
#region 八、系统自带特性 -- 外部DLL包函数特性
// DllImport
// 一般用来调用 C或C++ 的DLL写好的方法
// 命名空间 :using System.Runtime.InteropServices;
#endregion
class Program
{
// 条件编译特性
[Conditional("USE_FUN")]
static void FunConditional()
{
Console.WriteLine("函数 FunConditional 被调用");
}
static void Main(string[] args)
{
#region 特性的使用
MyClass mc = new MyClass();
Type typeMc = mc.GetType();
Console.WriteLine("-------------特性的使用-------------------");
// 判断是否使用了某个特性
if (typeMc.IsDefined(typeof(MyCustomAttribute), false)) // 是否搜索继承链
{
Console.WriteLine("typeMc 使用了 MyCustomAttribute 特性");
}
// 获取特性信息
object[] attrArray = typeMc.GetCustomAttributes(true);
for (int i = 0; i < attrArray.Length; i++)
{
if (attrArray[i] is MyCustomAttribute)
{
string info = (attrArray[i] as MyCustomAttribute).info;
Console.WriteLine(info);
(attrArray[i] as MyCustomAttribute).AttributeFun();
}
}
#endregion
#region 系统自带特性
// 过时特性
Console.WriteLine("-------------过时特性-------------------");
TestClass testObj = new TestClass();
testObj.OldSpeek("过时函数-- 123");
// 调用者信息特性
Console.WriteLine("-------------调用者信息特性-------------------");
testObj.SpeekCaller("567");
// 条件编译特性
Console.WriteLine("-------------条件编译特性-------------------");
FunConditional();
// 导出 C/C++ dll中的函数
// [DllImport("test.dll")]
// public static extern int add(int a, int b);
#endregion
#region 总结
// 特性是用于 为元数据再添加更多的 额外信息
// (变量, 方法)
// 可用通过反射 获取这些 额外信息。
// 自定义特性 继承自 --> Attribute
// 系统自带特性
#endregion
Console.ReadLine();
}
}
}
C# 特性的使用
最新推荐文章于 2024-07-14 20:44:00 发布