In this article, we will {
Tagshow (Event)
} "> The configuration is analyzed and discussed. The configuration part is far-fetched. However, I always think this configuration part is relatively independent and there are many references for blogengine. net design and implementation.
In an enterprise-level application system, it is essential to configure some system global parameters. How do we handle these configurations?
Generally, there are three steps as follows:
1. Some variable parameters are extracted during business module development.
2. When all business modules are developed, these parameters are classified {
Tagshow (Event)
} "> Store it.
3. Develop corresponding management functions to allow users to set these parameters.
I believe that most developers directly operate on the data in the database. some well-developed systems may make separate pages for user management and use. In essence, they all directly deal with the database, there is not much logic involved. It is more direct. However, in blogengine. Net's {
Tagshow (Event)
} "> Architecture {
Tagshow (Event)
} "> This operation becomes invalid in the model. We cannot perform this operation on the blogengine.. NET database to modify the data in the operating system (unless the application is restarted), because blogengine.. NET database only completes data storage, and all business logic is in blogengine. the core layer is maintained by the object state (refer to my second article ). Someone may wonder if you can further develop a dependency on database tables like cache in ASP. NET {
Tagshow (Event)
} "> Mechanism. I think this problem depends on the requirements. This does not seem to be necessary in blogengine. net.
So how does blogengine. Net implement global settings?
In {
Tagshow (Event)
} "> After installing blogengine. net, go to the background management. We will see many configuration options for classification, including the topic ,{
Tagshow (Event)
} "> Language, culture, and time zone. The logic processing of these configurations is completed through a class in blogengine. Core, that is, blogsettings. Blogsettings only completes blogengine. net global configuration processing. Some specific configurations of widgets described later are not completed here. This is mainly for the purpose of independent configuration, so that widgets can be developed independently.
Blogsettings ):
Attachment: blogsetting.jpg
In addition to the corresponding properties of various configuration items in blogsettings, there is also a static changed event to notify the external global configuration that has changed, so that more extensions can be written. Blogsettings is implemented in singleton mode ({
Tagshow (Event)
} "> The global configuration is system-unique for well-designed applications ).
- 1/** // <summary>
- 2 // public event used to indicate in settings have been changed.
- 3 /// </Summary>
- 4 public static event eventhandler <eventargs> changed;
- 5/** // <summary>
- 6 // Private member to hold Singleton instance.
- 7 /// </Summary>
- 8 Private Static blogsettings blogsettingssingleton;
- 9
- 10 instance # region instance
- 11/*** // <summary>
- 12 // gets the singleton instance of the <see CREF = "blogsettings"/> class.
- 13 /// </Summary>
- 14 // <value> A singleton instance of the <see CREF = "blogsettings"/> class. </value>
- 15 /// <remarks> </remarks>
- 16 public static blogsettings instance
- 17 {
- 18 get
- 19 {
- 20 if (blogsettingssingleton = NULL)
- 21 {
- 22 blogsettingssingleton = new blogsettings ();
- 23}
- 24 return blogsettingssingleton;
- 25}
- 26}
- 27 # endregion
Copy code
Here we can understand why direct modification to the data source cannot be reflected in the running system of blogengine. net.
Blogsettings executes a load method during object construction to load configuration information in all data storage. This loading process is applied. net reflection technology, find the configuration item with the same name as the object property in data storage and forcibly convert its value to the property, of course, the data access here is obtained through the blogservice call described in my third article. Similarly, the configuration is modified by saving the data back to the data storage and using reflection.
- 1 blogsettings () # region blogsettings ()
- 2/** // <summary>
- 3 // initializes a new instance of the <see CREF = "blogsettings"/> class.
- 4 /// </Summary>
- 5 private blogsettings ()
- 6 {
- 7 load ();
- 8}
- 9 # endregion
- 10
- 11 load () # region load ()
- 12/*** // <summary>
- 13 // initializes the singleton instance of the <see CREF = "blogsettings"/> class.
- 14 /// </Summary>
- 15 private void load ()
- 16 {
- 17 type settingstype = This. GetType ();
- 18
- 19 //------------------------------------------------------------
- 20 // Enumerate through individual settings nodes
- 21 //------------------------------------------------------------
- 22 system. Collections. Specialized. stringdictionary DIC = providers. blogservice. loadsettings ();
- 23
- 24 foreach (string key in DIC. Keys)
- 25 {
- 26 //------------------------------------------------------------
- 27 // extract the setting's name/value pair
- 28 //------------------------------------------------------------
- 29 string name = key;
- 30 string value = DIC [Key];
- 31
- 32 //------------------------------------------------------------
- 33 // Enumerate through public properties of this instance
- 34 //------------------------------------------------------------
- 35 foreach (propertyinfo propertyinformation in settingstype. getproperties ())
- 36 {
- 37 //------------------------------------------------------------
- 38 // determine if configured setting matches current setting based on name
- 39 //------------------------------------------------------------
- 40 if (propertyinformation. Name. Equals (name, stringcomparison. ordinalignorecase ))
- 41 {
- 42 //------------------------------------------------------------
- 43 // attempt to apply configured setting
- 44 //------------------------------------------------------------
- 45 try
- 46 {
- 47 propertyinformation. setvalue (this, convert. changetype (value, propertyinformation. propertytype, cultureinfo. currentculture), null );
- 48}
- 49 catch
- 50 {
- 51 // todo: log exception to a common logging framework?
- 52}
- 53 break;
- 54}
- 55}
- 56}
- 57 storagelocation = providers. blogservice. getstoragelocation ();
- 58}
- 59 # endregion
- 60
- 61 save () # region save ()
- 62/*** // <summary>
- 63 // saves the settings to disk.
- 64 /// </Summary>
- 65 public void save ()
- 66 {
- 67 system. Collections. Specialized. stringdictionary DIC = new system. Collections. Specialized. stringdictionary ();
- 68 type settingstype = This. GetType ();
- 69
- 70 //------------------------------------------------------------
- 71 // Enumerate through settings Properties
- 72 //------------------------------------------------------------
- 73 foreach (propertyinfo propertyinformation in settingstype. getproperties ())
- 74 {
- 75 try
- 76 {
- 77 If (propertyinformation. Name! = "Instance ")
- 78 {
- 79 //------------------------------------------------------------
- 80 // extract property value and its String Representation
- 81 //------------------------------------------------------------
- 82 object propertyvalue = propertyinformation. getvalue (this, null );
- 83 string valueasstring = propertyvalue. tostring ();
- 84
- 85 //------------------------------------------------------------
- 86 // format null/default property values as empty strings
- 87 //------------------------------------------------------------
- 88 If (propertyvalue. Equals (null ))
- 89 {
- 90 valueasstring = string. empty;
- 91}
- 92 If (propertyvalue. Equals (int32.minvalue ))
- 93 {
- 94 valueasstring = string. empty;
- 95}
- 96 If (propertyvalue. Equals (single. minvalue ))
- 97 {
- 98 valueasstring = string. empty;
- 99}
- 100
- 101 //------------------------------------------------------------
- 102 // write property name/value pair
- 103 //------------------------------------------------------------
- 104 DIC. Add (propertyinformation. Name, valueasstring );
- 105}
- 106}
- 107 catch {}
- 108}
- 109
- 110 providers. blogservice. savesettings (DIC );
- 111 onchanged ();
- 112}
- 113 # endregion
Copy code
Client usage (note: the client here refers to the user or caller of blogsettings)
- 1 // get SMTP Server
- 2 string Server = blogsettings. instance. smtpserver;
- 3
- 4 // set SMTP Server
- 5 blogsettings. instance. smtpserver = "hostname ";
- 6 blogsettings. instance. Save ();
Copy code
Summary
From the global configuration section of blogengine. net, we can learn the following points:
1. How the singleton mode is applied in real projects.
2. The implementation of the data access part of the configuration item has a good reference value. You can understand the convenience of. Net reflection for development.
3. The use of static events (blogengine. Net has many examples) allows us to make some external extensions, such as developing a tracking system for monitoring configuration modification.
A good design can be achieved only after constant reconstruction.