Attribute)
The definition provided by MSDN:
Attribute Class associates predefined system information or user-defined custom information with the target element. The target element can be an assembly, class, constructor, Delegate, enumeration, event, field, interface, method, executable file module, parameter, Property), return value, structure, or other attributes ).
In. Net programs, attributes can be used to solve many problems. For example, Mark interface functions in WebService as WebMethod, and Mark classes as serializable.
In addition, we can also customize Attribute to implement the functions we need. However, the custom Attribute must inherit from the Attribute class. There are many methods or attributes in Attribute, which provide us with powerful functions. Generally, we use Attribute through reflection.
Next we will talk about our experiences based on the actual project usage.
Requirement: the project has a dedicated logstore. Currently, the project requires the front-end functions such as querying, turning pages, and sorting by fields. Because the log data may have invalid data and the data volume is large. Many temporary tables have been created to improve statistics and paging performance. If a temporary table is created for a different requirement in the actual operation, resulting in a lot of code duplication and bloated, and it is not easy to manage in a unified manner, the solution is to create a temporary table in a unified manner through Attribute.
The main idea is as follows: use custom features to describe the type, length, and other information of fields in the temporary table to be created, and then obtain the characteristics corresponding to these fields through reflection, then construct the corresponding SQL command to create a temporary table.
The features are defined as follows:
[AttributeUsage (AttributeTargets. Property)]
Public class TableFieldAttribute: Attribute
{
/// <Summary>
/// Field Length
/// </Summary>
Public int Length {get; set ;}
/// <Summary>
/// Field description
/// </Summary>
Public string Describe {get; set ;}
/// <Summary>
/// Field Type
/// </Summary>
Public string Type {get; set ;}
}
The above AttributeUsage is also a class inherited from the Attribute. Its function is to mark the use range of the custom class, such as fields, attributes, classes, and methods. And use our custom class
Indicates whether the subclass of the marked class inherits the feature.
With this custom feature, you can apply it to entities.
Public class TableEntity
{
[TableField (Describe = "Guid primary key", Length = 36, Type = "uniqueidentifier")]
Public Guid {get; set ;}
[TableField (Describe = "name", Length = 36, Type = "varchar")]
Public string Name {get; set ;}
}
In this way, we have defined the data type, length, and so on. When you actually want to create a temporary table, you can construct the corresponding SQL command by reflecting the object of the temporary table to be created.
Definition of tool class: public class Tools <T> where T: class. In actual use, replace the generic type with the corresponding type.
This section describes how to use reflection to obtain the Information Code of specific fields in a temporary table:
Public static List <Record> GetTableFieldsInformation ()
{
Type t = typeof (T );
PropertyInfo [] propertyInfos = t. GetProperties ();
List <Record> tableEntities = new List <Record> ();
PropertyInfos. ToList (). ForEach (property =>
{
IList <CustomAttributeData> list = property. GetCustomAttributesData ();
If (list. Count = 1)
{
TableEntities. Add (GetTableEntity (list [0]. NamedArguments, property ));
}
Else
{
Throw new Exception ();
}
});
Return tableEntities;
}
In this way, the List returned by the GetTableFieldsInformation () method is a List containing all the information of a field in the temporary table. We cyclically list and construct SQL commands
The main code is as follows:
RecordEntities. ForEach (record =>
{
If (I = 0)
{
SQL = "CREATE TABLE [" + record. TableName + "] (";
}
If (list. All (item =>! Record. Type. Equals (item, StringComparison. OrdinalIgnoreCase )))
{
SQL + = string. Format ("{0} {1} ({2}),", record. FieldName, record. Type, record. Length );
}
Else
{
SQL + = string. Format ("{0} {1},", record. FieldName, record. Type );
}
I ++;
});
After the program is finally executed, such:
This is the main idea. In addition, if you are careful, you will find that the AttributeUsage feature usage is different from the TableFieldAttribute usage method I have defined.
TableFieldAttribute usage: [TableField (Describe = "Guid primary key", Length = 36, Type = "uniqueidentifier")]
AttributeUsage usage: [AttributeUsage (AttributeTargets. Property)].
This is also a custom feature. Why is the definition different from that in the Framework library .? Use Reflect to check the AttributeUsage source code, such:
From the mark point of view, the attribute Definition [AttributeTargets ValidOn] In AttributeUsage is different from that of the constructor.
If you are interested in in-depth research, you can try it on your own.
Note: The use of features is a powerful feature. In this example, only a small part is used. Therefore, only descriptions are provided in actual applications. In addition, the Code is not carefully organized
Code download: http://www.bkjia.com/uploadfile/2011/1025/20111025113636140.rar
From: tyb1222