1. Definition and function of Attribute:

The common language runtime allows you to add keyword-like description declarations called Attributes, which annotate elements in your program, such as types, fields, methods, and attributes. Attributes are stored together with metadata from Microsoft.net Framework files and can be used to describe your code to the runtime or to influence the behavior of your application while it is running. For example, serialization is commonly used in WCF. For example, the added [DataMenber] is a tag. The same goes for XML serialization.

2.Reflect’s definition and role

Reflection can be used to observe and modify program execution at run time. A Reflection -oriented program component can monitor code execution within a scope and modify itself to the desired goal associated with this scope. This is usually done by dynamically allocating program code at run time. In object-oriented programming languages such as Java, reflection allows classes, interfaces, fields, and methods to be examined at run time without the names of the interfaces, fields, and methods being known at compile time. It also allows you to instantiate new objects and call methods. The state of all method property fields in a class can be easily retrieved by reflection.

3. For a better understanding of reflection and Attribute application, here is an example.

The business background is as follows: You have a Person object, which currently has only Name and Num attributes, and then use a method to verify the validity of the Person object.

1.Name is mandatory. If Name is empty, “Name cannot be empty “is displayed.

2.Num can be empty, but must consist of numbers if any. If it is a non-number string, “Format is not correct” is displayed.

3.Address can be empty. If there is any data, the length cannot exceed 12.

Consider this: For the Person class, the familiar judgment rules may change, and attributes may be added or subtracted.

4. Solution 1:

For a conventional solution, you might think. At present, there are only three attributes Name,Address,Num, each time I write three code sections to verify the Name,Address,Num. If you add attributes, such as the public attribute EmailAddress, you must add code to verify that the string is a mailbox. If you remove an attribute, you remove the code that determines whether the attribute is qualified. That’s what I started with. But the downside is that it’s not maintainable. It’s a big change. And it can lead to duplicate code. How about if you change the requirement to Address can’t be empty. If address is valid or not, add a case that cannot be null.

5. Solution 2:

In order to solve the problem of solution one, we can actually use attributes and reflection. Here’s the idea:

5.1 First we create a PersonCheckAttribute object that inherits from System.attribute.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; Namespace ReflectTest. Model {public class PersonCheckAttribute: Attribute {/ / three bool variable is used to determine is to verify the information private bool checkEmpty = false; Private bool checkMaxLength = false; // Maximum Length private bool checkRegex = false; Private int maxLength = 0; private int maxLength = 0; private string regexStr = string.Empty; public bool CheckEmpty { get { return this.checkEmpty; } set { this.checkEmpty = value; } } public bool CheckMaxLength { get { return this.checkMaxLength; } set { this.checkMaxLength = value; } } public bool CheckRegex { get { return this.checkRegex; } set { this.checkRegex = value; } } public int MaxLength { get { return this.maxLength; } set { this.maxLength = value; } } public string RegexStr { get { return this.regexStr; } set { this.regexStr = value; }}}}Copy the code

5.2 Then let’s add the Person class. Pay attention to the label inside.

For the 5.1 PersonCheckAttribute class, the bool variable is used to determine whether validation is required, and the public attribute is used to access judgment parameters.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ReflectTest.Model { public class Person { [PersonCheck(CheckEmpty=true)] public string Name { get; set; } [PersonCheck(CheckRegex = true, RegexStr = "^[0-9]*[1-9][0-9]*$")] public string Num { get; set; } [PersonCheck(CheckMaxLength = true, MaxLength = 12)] public string Address { get; set; }}}Copy the code

Now that we’re done with attributes, let’s look at how to use reflection to get the common attributes of a class and the attributes for each Attribute.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using ReflectTest.Model; using System.Reflection; using System.Text.RegularExpressions; Namespace ReflectTest.Business {public class PersonCheck {public static String GetErrorMessage(Person person) { PropertyInfo[] propertyInfos = person.GetType().GetProperties(); // Get all the attributes of a class. String errorMsg = string.empty; Foreach (PropertyInfo info in propertyInfos) {errorMsg += GetSignalPropertity(info, person); } return errorMsg; } // Get a single public Attribute. This is the [PersonCheck] information in the Model class. Private Static String GetSignalPropertyInfo PropertyInfo,Person Person) {// Since there is only one Attribute per property for this example, first() is used, // However, You must add the [PersonCheck] tag to the attribute, but you don't have to set the emoticon field. GetCustomAttributes() returns null. Pointing to the first complains. / / PersonCheckAttribute attribute = propertyInfo. The GetCustomAttributes () first () as PersonCheckAttribute; string errorMsg = string.Empty; // The following if statement is used to determine the Settings in the tag, Set up what is executed what data validation PersonCheckAttribute attribute = propertyInfo. GetCustomAttribute (typeof (PersonCheckAttribute)) as PersonCheckAttribute; if (attribute ! = null) { if (attribute.CheckEmpty) { string obj = propertyInfo.GetValue(person) as string; If (string.isNullorempty (obj)) {errorMsg += environment.newline + String.format ("{0} cannot be null ", propertyInfo.name); } } if (attribute.CheckMaxLength) { string obj = propertyInfo.GetValue(person) as string; if (obj ! ErrorMsg += environment.newline + string.Format("{0} cannot exceed the maximum value {1}", propertyInfo.Name, attribute.MaxLength); If (attribute.checkregex) {string obj = propertyInfo.getValue (person) as string; Regex regex = new Regex(attribute.RegexStr); if (obj ! = null && ! Regex.ismatch (obj)) {errorMsg += environment.newline + string.Format("{0} Format is incorrect ", propertyInfo.name); } } } return errorMsg; }}}Copy the code

 

5.4 The following is the running result.

Person p = new Person(){Num= “ABC”}; The GetErrorMessage(Person Person) method is called and runs as follows. Person cannot be empty.

    

5.4.2 If Person p = new Person(){Num= “123”, Address= “Chengdu,Tianfu SoftwarePark”}; The GetErrorMessage(Person Person) method is called and runs as follows. Person cannot be empty.

  

6. Analyze the benefits of reflection:

If I need to change it, Address can’t be empty anymore. I just set CheckEmpty=true in the Address tag, and I don’t need to change the logic. Similarly, if you were to add the EmailAddress attribute to the Person class, PersonCheck(CheckRegexStr = true,regexStr=”*”) * is not a valid regular expression.

 

7. Conclusion:

In fact, younger brother is also just contact reflex. A lot of things are also half-baked. At present, the understanding of reflection is so much, there are other big bull to apply more in this area, if there are any good ideas and information please share, learn from each other, mutual improvement. Code link: github.com/FourLeafClo…