1. Reflection
The program is used to process data. Text and characteristics are data. The program itself (class definition and class in BLC) is also data. The data about the program and its type is called metadata and stored in the assembly of the program.
The behavior of a running program to view its own metadata or the metadata of other assemblies is called reflection.
1.1 Type
Predefined types (int, long, string, etc.), types in BCL (Console,IEnumerable, etc.) and programmer defined types (MyClass,MyDel, etc.). Each type has its own members and properties. The type abstract class is used to contain the properties of the type. Objects using this class can get information about the types used by the program. Type is an abstract class and cannot instantiate an object.
1.2 get Type object
Create a class that declares fields, properties, and methods
class MyClass { private int id; private int age; public int number; public string Name { get; set; } public string Name2 { get; set; } public string Name3 { get; set; } public void Test1() { } public void Test2() { } }
static void Main(string[] args) { Each class corresponds to one type Object, this type Object stores the methods, data and members of this class MyClass my = new MyClass();//The data in a class is stored in the object, but the type object only stores the members of the class Type type = my.GetType();//Get the Type object of the class to which this object belongs through the object Console.WriteLine(type.Name);//Gets the name of the class Console.WriteLine(type.Namespace);//Gets the namespace where the Console.WriteLine(type.Assembly);//Class assembly FieldInfo[] array = type.GetFields();//Get the fields of the class. Only public fields can be obtained foreach (FieldInfo info in array) { Console.Write(info.Name + " "); } PropertyInfo[] array2 = type.GetProperties();//Get property name foreach (PropertyInfo info in array2) { Console.Write(info.Name + " "); } MethodInfo[] array3 = type.GetMethods();//Get method name foreach (MethodInfo info in array3) { Console.Write(info.Name + " "); } Console.ReadKey(); }
Operation results:
1.3 get assembly
class Program { static void Main(string[] args) { MyClass my = new MyClass(); Assembly assem = my.GetType().Assembly;//Get the Assembly assembly of the class through its type object Console.WriteLine(assem.FullName);//Gets the full name of the assembly Type[] types = assem.GetTypes();//Gets all types in the assembly foreach (var type in types) { Console.WriteLine(type); } Console.ReadKey(); } }
Operation results:
2. Characteristics
An attribute is a language structure that allows us to add metadata to an assembly of an assembly. It is a special type of class used to store program structure information.
The program structure to which features are applied is called a goal. For example, the following methods or parameters applied to features are called goals.
Programs designed to obtain and use metadata (object browsers) are called feature consumers. For example, the method that the VS compiler reads the Obsolete feature is discarded, and the compiler is the consumer of this feature.
2.1 Obsolete characteristics
class Program { [Obsolete("This method is deprecated. Please use the latest one NewTest method")]//Properties: deprecated static void Test() { Console.WriteLine("Test"); } static void NewTest() { Console.WriteLine("NewTest"); } static void Main(string[] args) { Test(); } }
When the mouse hovers over the discarded method, the corresponding prompt will be given
2.2 Conditional features:
#define IsShowMessage //Define a macro. Only when it is defined can the method of IsShowMessage attribute be called class Program { [Conditional("IsShowMessage")] static void ShowMessage(string str) { Console.WriteLine(str); } static void Main(string[] args) { ShowMessage("Start of Main"); Console.WriteLine("Doing work"); ShowMessage("End of Main"); } }
Operation results:
When no macro is defined, the method of the IsShowMessage attribute is not called
2.3 caller information characteristics
class Program { static void ShowMessage(string message,[CallerLineNumber]int lineNumber = 0,[CallerFilePath]string filePath="",[CallerMemberName]string memberName="") { Console.WriteLine(message); Console.WriteLine(lineNumber);//Number of lines of code calling this method Console.WriteLine(filePath);//The file path where this method is called Console.WriteLine(memberName);//The name of the method that called this method } static void Main(string[] args) { ShowMessage("Hello"); } }
Operation results:
2.4 DebuggerStepThrough feature
When the power-off is set for debugging, the structure of this feature will not be interrupted. It will be interrupted after running the structure directly, for example:
class Program { [DebuggerStepThrough] static void ShowMessage(string message,[CallerLineNumber]int lineNumber = 0,[CallerFilePath]string filePath="",[CallerMemberName]string memberName="") { Console.WriteLine(message); Console.WriteLine(lineNumber);//Number of lines of code calling this method Console.WriteLine(filePath);//The file path where this method is called Console.WriteLine(memberName);//The name of the method that called this method } static void Main(string[] args) { ShowMessage("Hello"); Console.WriteLine("helloworld") } }
Adding breakpoints to the two fields of the Main method will not jump into the ShowMessage method. The next step will be directly interrupted in the second line
2.5 custom properties
//The attribute class should represent some state of the target structure //If the attribute requires some fields, data can be collected by including a constructor with positional parameters, and optional fields can be initialized on demand with named parameters //Do not implement public methods and other function members other than properties //The attribute class is declared sealed //Use AttributeUsage in the attribute declaration to specify the attribute target group [AttributeUsage(AttributeTargets.Class)] internal sealed class InformationAttribute:Attribute { public string developer; public string version; public string description; public InformationAttribute(string developer, string version, string description) { this.developer = developer; this.version = version; this.description = description; } }
//Access characteristics [Information("Cheese","1.1","Rocket launching class")] internal class Program { static void Main(string[] args) { //Call the IsDefined method through the Type object Type t = typeof(Program); //IsDefined access feature to judge whether a feature is applied to the class bool result = t.IsDefined(typeof(InformationAttribute), false); Console.WriteLine(result); //To return an array of object s, we must cast it into the attribute type of the corresponding type //The bool parameter specifies whether it searches the inheritance tree for attributes //When this method is called, each instance of the feature associated with the target is created object[] attArray = t.GetCustomAttributes(false); } }