Application of reflection and attribute in ORM
I. Reflection
What is reflection?
To put it simply, reflection is a way to dynamically obtain object information at runtime, such as knowing the attributes, methods, and delegation of an object at runtime.
What is the purpose of reflection?
Reflection not only allows you to obtain object information during running, but also provides the ability to dynamically call object methods and dynamically set and obtain attributes during running.
What is the use of reflection in Orm?
The ORM implementation I discussed here describes the ing rules through custom attribute. However, we do not know which table the specific object needs to correspond to, and these objects are independent of our ORM framework. Therefore, we can only use custom attribute to define the ing rules, then, the ing rules are dynamically obtained through reflection.
Reflection implementation:
Next we will discuss it in a simple way to get the object's property value. Suppose we have class person, which has three attributes: name, age, and sex. We use the Reflection Method to dynamically obtain the values of these three attributes of the person object.
- Public class person
- {
- Private string _ name;
- Private int _ age;
- Private string _ sex;
- Public string name
- {
- Get {return this. _ name ;}
- Set {This. _ name = value ;}
- }
- Public int age
- {
- Get {return this. _ age ;}
- Set {This. _ age = value ;}
- }
- Public String sex
- {
- Get {return this. _ sex ;}
- Set {This. _ sex = value ;}
- }
- }
The test code is as follows:
- Static class Program
- {
- [Stathread]
- Static void main ()
- {
- Person = new person ();
- Person. Name = "Snoopy ";
- Person. Age = 5;
- Person. Sex = "male ";
- Propertyinfo [] Infos = person. GetType (). getproperties ();
- Console. writeline ("Print attributes ");
- Foreach (propertyinfo info in Infos)
- {
- // Obtain and print attributes
- Console. writeline (info. Name + ":" + info. getvalue (person, null ));
- }
- Console. writeline ("set person. Name = hellokitty ");
- // Set attributes and name attributes
- Foreach (propertyinfo info in Infos)
- {
- If (info. Name = "name ")
- {
- Info. setvalue (person, "hellokitty", null );
- }
- }
- Console. writeline ("Print attributes ");
- Foreach (propertyinfo info in Infos)
- {
- // Obtain and print attributes
- Console. writeline (info. Name + ":" + info. getvalue (person, null ));
- }
- Console. Read ();
- }
- }
The above demonstrates how to dynamically obtain and set object attributes through reflection. But what does this have to do with orm and attribute? This is what we will do next.
Ii. Use of attribute:
Although attribute Chinese translation is also known as "attribute", it is totally different from the attribute of an object. She describes the object or object attributes, methods, delegates, and so on at runtime. It is used to describe your code or affect the behavior of your program at runtime.
In fact, we often see attribute in C # programming, but we didn't pay attention to it. For example, the "[stathread]" before the main function is actually an attribute. The entire process is [stathreadattribute]. In addition, specify the serializable [serializable] of the class. Are you familiar with this? However, it is estimated that it is useless at ordinary times, so I did not pay attention to it.
Since attribute is a class, its definition method and class are no different. The only difference is that the custom attribute class must inherit from system. attribute.
Next we will briefly define an attribute that describes the field information of the database. In this class, we will omit it and only provide "field name" and "field type ":
- Public class datafieldattribute: attribute
- {
- Private string _ fieldname;
- Private string _ fieldtype;
- Public datafieldattribute (string fieldname, string fieldtype)
- {
- This. _ fieldname = fieldname;
- This. _ fieldtype = fieldtype;
- }
- Public String fieldname
- {
- Get {return this. _ fieldname ;}
- Set {This. _ fieldname = value ;}
- }
- Public String fieldtype
- {
- Get {return this. _ fieldtype ;}
- Set {This. _ fieldtype = value ;}
- }
- }
Well, we have our own attribute to describe the database field, so now we apply it to the actual class. We continue to use the person class as follows:
- Public class person
- {
- Private string _ name;
- Private int _ age;
- Private string _ sex;
- [Datafieldattribute ("name", "nvarchar")]
- Public string name
- {
- Get {return this. _ name ;}
- Set {This. _ name = value ;}
- }
- [Datafieldattribute ("Age", "int")]
- Public int age
- {
- Get {return this. _ age ;}
- Set {This. _ age = value ;}
- }
- [Datafieldattribute ("sex", "nvarchar")]
- Public String sex
- {
- Get {return this. _ sex ;}
- Set {This. _ sex = value ;}
- }
- }
Through custom attribute, we define the one-to-one correspondence between class attributes and database fields. We add attribute descriptions to the name, age, and sex attributes of the person class, the field names and types corresponding to them are specified, where person. name corresponds to the field name. The field type is nvarchar ....
Iii. Joint Use of reflection and attribute.
From the above description, we understand reflection, attribute, and ORM ing rules. However, it may be confusing for new contacts. How can we dynamically obtain these ing rules? Let's hear from you.
This requires reflection:
In the following example, we add the datafieldattribute description to the name, age, and sex of person, which is actually adding the ing rules of O (object)/R (relational database, next we will use the Reflection Method to dynamically obtain this ing rule:
- Static class Program
- {
- [Stathread]
- Static void main ()
- {
- Person = new person ();
- Person. Name = "Snoopy ";
- Person. Age = 5;
- Person. Sex = "male ";
- Propertyinfo [] Infos = person. GetType (). getproperties ();
- Object [] objdatafieldattribute = NULL;
- Foreach (propertyinfo info in Infos)
- {
- Objdatafieldattrites = info. getcustomattributes (typeof (datafieldattrites), false );
- If (objdatafieldattribute! = NULL)
- {
- Console. writeline (info. Name + "-> database field:" + (datafieldattribute) objdatafieldattribute [0]). fieldname );
- }
- }
- }
- }
Haha, do you really want to do it? Of course, if you start this step, I will be very happy, indicating that my description is still clear (Note: This is not valid for the big players who already know it ). It also shows that you are very competent. The next step is to dynamically obtain the ing rules from the object based on this method, and dynamically construct statements such as insert, update, and delete.
Iv. Summary in this Chapter
In this chapter, I have introduced in detail the concepts and applications of reflection and custom attribute, as well as how to dynamically obtain the ing rules of O/R Mapping at runtime. Of course, the code here is just an example. To implement an Orm, we still need to consider a lot, such:
1. Which database table does person correspond?
2. What is the expression of PK and FK in person (if any?
......
These questions will be explained in my next article.
Related connections:
C # basic series: implement your own ORM (basic concepts of ORM)
C # basic series: implement your own ORM (build my own ORM)
C # basic series: implement your own ORM (miniorm test code)
Source code download
Share:
- Previous Article: C # basic series: implementing your own ORM (basic concepts of ORM)
- Next article: C # basic series: implement your own ORM (build my own ORM)