diff --git a/C#进阶/C#进阶.sln b/C#进阶/C#进阶.sln index 18454a4..8d99eea 100644 --- a/C#进阶/C#进阶.sln +++ b/C#进阶/C#进阶.sln @@ -89,6 +89,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson20_反射练习", "Le EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "反射练习库", "反射练习库\反射练习库.csproj", "{86839643-1A23-454E-8B06-839900B3E032}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson21_特性", "Lesson21_特性\Lesson21_特性.csproj", "{806658BC-2943-461C-BD60-D3B51F0BA223}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson21_特性练习", "Lesson21_特性练习\Lesson21_特性练习.csproj", "{5C3AFDDF-23DF-4C9E-8335-42DB430D2EE4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -267,6 +271,14 @@ Global {86839643-1A23-454E-8B06-839900B3E032}.Debug|Any CPU.Build.0 = Debug|Any CPU {86839643-1A23-454E-8B06-839900B3E032}.Release|Any CPU.ActiveCfg = Release|Any CPU {86839643-1A23-454E-8B06-839900B3E032}.Release|Any CPU.Build.0 = Release|Any CPU + {806658BC-2943-461C-BD60-D3B51F0BA223}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {806658BC-2943-461C-BD60-D3B51F0BA223}.Debug|Any CPU.Build.0 = Debug|Any CPU + {806658BC-2943-461C-BD60-D3B51F0BA223}.Release|Any CPU.ActiveCfg = Release|Any CPU + {806658BC-2943-461C-BD60-D3B51F0BA223}.Release|Any CPU.Build.0 = Release|Any CPU + {5C3AFDDF-23DF-4C9E-8335-42DB430D2EE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5C3AFDDF-23DF-4C9E-8335-42DB430D2EE4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5C3AFDDF-23DF-4C9E-8335-42DB430D2EE4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5C3AFDDF-23DF-4C9E-8335-42DB430D2EE4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/C#进阶/Lesson21_特性/Lesson21_特性.csproj b/C#进阶/Lesson21_特性/Lesson21_特性.csproj new file mode 100644 index 0000000..2150e37 --- /dev/null +++ b/C#进阶/Lesson21_特性/Lesson21_特性.csproj @@ -0,0 +1,10 @@ + + + + Exe + net8.0 + enable + enable + + + diff --git a/C#进阶/Lesson21_特性/Program.cs b/C#进阶/Lesson21_特性/Program.cs new file mode 100644 index 0000000..4578204 --- /dev/null +++ b/C#进阶/Lesson21_特性/Program.cs @@ -0,0 +1,182 @@ +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace Lesson21_特性 +{ + #region 知识点一 特性是什么 + //特性是一种允许我们向程序的程序集添加元数据的语言结构 + //它是用于保存程序结构信息的某种特殊类型的类 + + //特性提供功能强大的方法以将声明信息与 C# 代码(类型、方法、属性等)相关联。 + //特性与程序实体关联后,即可在运行时使用反射查询特性信息 + + //特性的目的是告诉编译器把程序结构的某组元数据嵌入程序集中 + //它可以放置在几乎所有的声明中(类、变量、函数等等申明) + + //说人话: + //特性本质是个类 + //我们可以利用特性类为元数据添加额外信息 + //比如一个类、成员变量、成员方法等等为他们添加更多的额外信息 + //之后可以通过反射来获取这些额外信息 + #endregion + + #region 知识点二 自定义特性 + //继承特性的基类 Attribute + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field, AllowMultiple = true, Inherited = false)] + class MyCustomAttribute : Attribute + { + //特性中的成员 一般根据需求来写 + public string info; + public MyCustomAttribute(string info) + { + this.info = info; + } + public void TestFunc() + { + Console.WriteLine("特性的方法"); + } + + } + #endregion + + #region 知识点三 特性的使用 + //基本语法 + //[特性名(参数列表)] + //本质上 就是在调用特性类的构造函数 + //写在哪里? + //类、函数、变量上一行,表示他们具有该特征信息 + + [MyCustom("额外信息例如说明")] + [MyCustom("额外信息例如说明")] + class MyClass + { + [MyCustom("12312321")] + public int value; + + public void TestFunc(int a) + { + + } + //[MyCustom("这是用来计算的函数")] + //public void TestFunc([MyCustom("函数参数")]int a) + //{ + + //} + } + #endregion + + #region 知识点四 限制自定义特性的使用范围 + //通过为特性类 加特性 限制其使用范围 + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true, Inherited = true)] + //参数一:AttributeTargets — 特性嫩个用在哪些地方 + //参数二:AllowMultiple — 是否允许多个特性实例用在同一个目标上 + //参数三:Inherited — 特性是否能被派生类和重写成员继承 + public class MyCustom2Attribute : Attribute + { + + } + #endregion + + #region 知识点五 系统自带特性——过时特性 + //过时的特性 + //Obsolete + //用于提示用户 使用的方法等成员已经过时 建议使用新方法 + //一般加在函数前的特性 + + class TestClass + { + //参数一:调用过时方法时 提示的内容 + //参数二: true-使用该方法时会报错 false-使用该方法时直接警告 + [Obsolete("OldSpeak方法已经过时了,请使用Speak方法", false)] + public void OldSpeak(string str) + { + + } + + public void Speak() + { + + } + public void SpeakCaller(string str, [CallerFilePath] string fileName = "", + [CallerLineNumber] int line = 0, [CallerMemberName] string target = "") + { + Console.WriteLine(str); + Console.WriteLine(fileName); + Console.WriteLine(line); + Console.WriteLine(target); + } + } + #endregion + + #region 知识点六 系统自带特性——调用者信息特征 + //哪个文件调用? + //CallerFilePath特性 + //哪一行调用? + //CallerLineNumber特性 + //哪个函数调用? + //CallerMemberName特性 + + //需要引用命名空间 using System.Runtime.CompilerServices; + //一般作为函数参数的特性 + #endregion + + #region 知识点七 系统自带特性——条件编译特性 + //条件编译特性 + //Conditional + //它会和预处理指令 #define配合使用 + + //需要引用命名空间using System.Diagnostics; + //主要可以用在一些调试代码上 + //有时想执行有时不想执行的代码 + #endregion + + #region 知识点八 系统自带特性——外部Dll包函数特性 + //DllImport + //用来标记非.Net(C#)的函数,表明该函数在一个外部的DLL中定义。 + //一般用来调用 C或者C++的Dll包写好的方法 + //需要引用命名空间 using System.Runtime.InteropServices + #endregion + class Program + { + [Conditional("Func")] + static void Func() + { + Console.WriteLine("Func执行"); + } + static void Main(string[] args) + { + #region 特性的使用 + MyClass c = new MyClass(); + Type t = c.GetType(); + //t.Assembly.GetType(); + //t = typeof(MyClass); + //t = Type.GetType("Lesson21_特性.MyClass"); + + //判断是否使用了某个特性 + //参数1:特性的类型 + //参数2:代表是否搜索继承链(属性和事件忽略此参数) + if (t.IsDefined(typeof(MyCustomAttribute), false) ) + { + Console.WriteLine("该类型应用了MyCustomAttribute特性"); + } + + //获取Type元数据中的所有特性 + object[] array = t.GetCustomAttributes(true); + for (int i = 0; i < array.Length; i++) + { + if (array[i] is MyCustomAttribute) + { + Console.WriteLine((array[i] as MyCustomAttribute).info); + (array[i] as MyCustomAttribute).TestFunc(); + } + } + #endregion + TestClass tc = new TestClass(); + tc.OldSpeak("1123"); + tc.Speak(); + tc.SpeakCaller("123123"); + + Func(); + } + } +} diff --git a/C#进阶/Lesson21_特性练习/Lesson21_特性练习.csproj b/C#进阶/Lesson21_特性练习/Lesson21_特性练习.csproj new file mode 100644 index 0000000..2150e37 --- /dev/null +++ b/C#进阶/Lesson21_特性练习/Lesson21_特性练习.csproj @@ -0,0 +1,10 @@ + + + + Exe + net8.0 + enable + enable + + + diff --git a/C#进阶/Lesson21_特性练习/Program.cs b/C#进阶/Lesson21_特性练习/Program.cs new file mode 100644 index 0000000..a917aec --- /dev/null +++ b/C#进阶/Lesson21_特性练习/Program.cs @@ -0,0 +1,43 @@ +using System.Reflection; + +namespace Lesson21_特性练习 +{ + internal class Program + { + static void Main(string[] args) + { + Assembly assembly = Assembly.LoadFrom(@"D:\VisualStudio2022\VisualStudio Programe\C#\C#进阶\反射练习库\bin\Debug\反射练习库"); + Type[] types = assembly.GetTypes(); + for (int i = 0; i < types.Length; i++) + { + Console.WriteLine(types[i]); + } + //得type + Type playertype = assembly.GetType("反射练习库.Player"); + //实例化对象 + object playerObj = Activator.CreateInstance(playertype); + Console.WriteLine(playerObj); + + FieldInfo[] fields = playertype.GetFields(); + for (int i = 0; i < fields.Length; i++) + { + Console.WriteLine(fields[i]); + } + + //首先得到自定义特性的Type + Type atrribute = assembly.GetType("反射练习库.MyCustomAttribute"); + + //赋值名字 + FieldInfo fieldStr = playertype.GetField("name"); + if(fieldStr.GetCustomAttribute(atrribute) != null) + { + Console.WriteLine("非法操作,随意修改name成员"); + } + else + { + //检测是否被自定义特性修饰 如果是 就不能更改 而是提示 + fieldStr.SetValue(playerObj, "123123"); + } + } + } +} diff --git a/C#进阶/反射练习库/test.cs b/C#进阶/反射练习库/test.cs index 6576ed9..2e12102 100644 --- a/C#进阶/反射练习库/test.cs +++ b/C#进阶/反射练习库/test.cs @@ -6,6 +6,10 @@ using System.Threading.Tasks; namespace 反射练习库 { + class MyCustomAttribute: Attribute + { + + } public struct Position { public int x; @@ -19,6 +23,7 @@ namespace 反射练习库 } public class Player { + [MyCustom()] public string name; public int hp; public int atk;