First, define an attribute ). I will put this feature on the attributes that need to be automatically loaded and saved, so that these attributes to be processed can be filtered out from all the page attributes for further processing. This feature is defined as follows:
/// <Summary>
/// Automatically save attributes. This function can automatically save and load fields or attribute values. This attribute takes effect only for non-static fields or attributes.
/// </Summary>
/// <Remarks>
/// Automatically save the property. Add this property to the property of the page class, so that the field or property can be automatically saved and loaded.
/// However, this attribute must be serializable. Otherwise, an exception is thrown. This attribute takes effect only on non-public fields or attributes.
/// </Remarks>
[Attributeusage (attributetargets. property | attributetargets. field, allowmultiple = false, inherited = false)]
Public class autosaveattribute: attribute
{
/// <Summary>
/// Initialize and create an instance of the <see cref = "autosaveattribute"/> class so that the attributes of the class with this property are automatically saved.
/// </Summary>
Public autosaveattribute (){}
}
Then, we will rewrite some page lifecycle events and add our processing code. The processing process is as follows: (1) retrieving the current page type and filtering out the attributes to be processed (initialization process); (2) saving or assigning values to the filtered attributes (key points ).
(I) filter the attributes to be processed, cache them to a static dictionary, and retrieve them as needed. The initialization code is as follows:
/// <Summary>
/// User control type and automatically save attribute member buffer Dictionary
/// </Summary>
Protected static dictionary <type, memberinfo []> cachedic = null;
/// <Summary>
/// Obtain the binding ID of the member list.
/// </Summary>
Protected static bindingflags flag;
/// <Summary>
/// Initialize the <see cref = "basepage"/> class.
/// </Summary>
Static basepage ()
{
Cachedic = new dictionary <type, memberinfo []> ();
Flag = bindingflags. public | bindingflags. nonpublic | bindingflags. instance | bindingflags. getfield | bindingflags. getproperty | bindingflags. flattenhierarchy;
}
/// <Summary>
/// Type of the current page
/// </Summary>
Protected type currtype = null;
/// <Summary>
/// Initialize the buffer Dictionary of the current page
/// </Summary>
Protected void initcachedic ()
{
// Obtain the current instance type
Currtype = page. gettype ();
Memberinfo [] mems = null;
If (! Cachedic. trygetvalue (currtype, out mems ))
{
// Automatically save attributes for processing
Var list = currtype. getmembers (flag)
. Where (p => attribute. isdefined (p, typeof (autosave), false ))
. Toarray ();
Cachedic [currtype] = list;
}
}
We can see that when calling the initialization function initcachedic, the system will do two things: cache the current page type and filter the attributes to be processed. Filter attribute reflection operations, which are not repeated once.