The comments from my friends in the previous article gave me a lot of motivation to write this {
Tagshow (Event)
} "> Series of articles, it seems that everyone is more concerned about this series. In the first half of this article, I will explain the overall structure of blogengine. net {
Tagshow (Event)
} "> Architecture, the second half is mainly for the analysis of business class.
After downloading the source code, open the solution. We found that blogengine. NET is divided into two projects in the project's organizational structure: blogengine. core, which is the core logic layer of blogengine. net. All business logic and some functions are embodied in this project. In fact, this core business layer also has a part of data access, that is, the provider mode. In blogengine. net, relational databases or XML have only one role, that is {
Tagshow (Event)
} "> Stores data. The ID generation of blogengine. Net business objects is controlled by the core layer, rather than the data storage part, because it supports more data sources. Unlike many other business systems, a database may contain many stored procedures, triggers, and functions to complete certain business operations and data processing. In blogengine.net, we can use a .txt file to develop a provider for blogengine. net, the method is very simple, as long as the implementation of blogprovider (blogengine. net), membershipprovider and roleprovider. In fact, blogengine. net is also used to a large extent. net itself classic {
Tagshow (Event)
} "> Model. Another project is a site, mainly for specific Web implementation, but the specific functions are completed by calling the core layer.
In fact, it is difficult for me to get started when I first read the source code of blogengine. net. In fact, it is no wonder that the official materials are mostly about use and development and expansion, and what you find in the Community is not what you want most. After studying for a while, I found that the entire blogengine. net are all centered around this business class. Other classes provide services for it or receive its messages, such as provider and extension. Businessbase is the base class of all business classes, which encapsulates Features shared by many business classes. Its sub-classes include:
Authorprofile: encapsulation of the user's profile.
Page: This class actually corresponds to a static article in blogengine. net. The difference between PAGE and post is not very important. If you are interested, refer to the official instructions.
Post: the most widely used class in blogengine. net, representing an article submitted by the author.
Category: Document category. An article can belong to multiple categories, and a parent category can be added to the category.
Is their inheritance relationship:
Attachment: businatease.jpg
Ipublishable {
Tagshow (Event)
} "> I will explain the interface in detail in future articles.
The prototype from businessbase
Business 8 prototype
1 public abstract class businessbase <type, key>: idataerrorinfo, inotifypropertychanged, ichangetracking, idisposable where type: businessbase <type, key>, new ()
2 {}
We can see that:
1. businworksheet is a generic class. This generic design is very good. type is used to identify the specific subclass type. Key is mainly the unique ID of the subclass object. This ID is of the string type in authorprofile, the GUID type is used in other classes such as page, so this generic setting is used only when the base class is defined.
2. The interfaces implemented by businessbase are also the interfaces that should be implemented by the Business Objects recommended by Microsoft.
Idataerrorinfo is used to identify the internal error information of an object. The implementation of this interface is mainly used to define {
Tagshow (Event)
} "> Verification rules.
The inotifypropertychanged user notifies the client that the data has changed. Mainly when the internal data of the object changes, for some bindings {
Tagshow (Event)
} "> Control Data {
Tagshow (Event)
} "> Synchronously update.
Ichangetracking is used to update data storage if the internal data of an object changes.
I don't need to explain this to idisposable. net.
From the above, we can see that all the subclass objects of businessbase have a notification that the attributes are changed externally when data is modified, and inotifypropertychanged is implemented to notify the bound control, implement ichangetracking to update data storage. Let's take a look at the source code and find that blogengine. Net has handed over data verification of all business objects to the validation model for processing. This is a clever application that unifies the verification model, which I recommend very much.
Validation
- 1 validation # region Validation
- 2
- 3 private stringdictionary _ brokenrules = new stringdictionary ();
- 4
- 5/** // <summary>
- 6 // add or remove a broken rule.
- 7 /// </Summary>
- 8 // <Param name = "propertyname"> The Name Of The property. </param>
- 9 // <Param name = "errormessage"> the description of the error </param>
- 10 /// <Param name = "isbroken"> true if the validation rule is broken. </param>
- 11 protected virtual void addrule (string propertyname, string errormessage, bool isbroken)
- 12 {
- 13 if (isbroken)
- 14 {
- 15_brokenrules [propertyname] = errormessage;
- 16}
- 17 else
- 18 {
- 19 if (_ brokenrules. containskey (propertyname ))
- 20 {
- 21 _ brokenrules. Remove (propertyname );
- 22}
- 23}
- 24}
- 25
- 26/** // <summary>
- 27 // reinforces the business rules by adding additional rules to
- 28 // broken rules collection.
- 29 /// </Summary>
- 30 Protected abstract void validationrules ();
- 31
- 32/** // <summary>
- 33 // gets whether the object is valid or not.
- 34 /// </Summary>
- 35 public bool isvalid
- 36 {
- 37 get
- 38 {
- 39 validationrules ();
- 40 return this. _ brokenrules. Count = 0;
- 41}
- 42}
- 43
- 44/*** // <summary>
- 45 // if the object has broken business rules, use this property to get access
- 46 // to the different validation messages.
- 47 /// </Summary>
- 48 Public Virtual string validationmessage
- 49 {
- 50 get
- 51 {
- 52 If (! Isvalid)
- 53 {
- 54 stringbuilder sb = new stringbuilder ();
- 55 foreach (string messages in this. _ brokenrules. values)
- 56 {
- 57 sb. appendline (messages );
- 58}
- 59
- 60 return sb. tostring ();
- 61}
- 62
- 63 return string. empty;
- 64}
- 65}
- 66
- 67 # endregion
Copy code
So what do we need to do for the subclass of businessbase? They need to override the data storage operation methods (through the provider call, mainly dataselect, etc.), which is also advocated for interface-oriented programming. Isnew, ischanged, and isdeleted are used for internal data processing. The programming model is unified, and a saveaction enumeration is defined to implement unified processing and notification message encapsulation.
Business interfaces provides two events that are triggered before and after the internal data is stored. They are pre-saved events and post-saved events, which are used to provide external access points, a bit similar to ASP. net, but these events are Class events, not belong to a certain object. In this way, the external can process the events before saving or the stored events. This model is very helpful for expansion. For example, we can easily record business logs and keep records consistent. In addition, businessbase overrides equal methods or operators for sorting and comparing two objects, which are common features of business objects.
So what do we implement after the derived class inherits from this base class? It is nothing more than its own data storage method, data validation rules, and its own ID type, note that each derived class provides a static attribute to extract the entire object list. You can also obtain the object list based on the specific query information, but they all belong to the class method, that is, the static method. For Derived classes with complex structures and relationships, for example, post contains the comment list and its corresponding methods to represent the relationship with the operation object. In addition, the markold method of the base class is used to identify the object that has been processed and does not need to be processed. The subclass can override this method to provide its own implementation. Some other methods or attributes are required in a specific class. This is a good analysis.
For example, for a client program, we only need to do this to complete data operations:
Add article:
- 1 post = New post ();
- 2 Post. datecreated = datatime. now;
- 3 Post. Author = "guo xingwang ";
- 4 post. Title = "blogengine. NET architecture and source code analysis series Part2: Business Object-common parent class businessbase ";
- 5 post. content = "xxxxxx ";
- 6 post. Description = "xxxxxx ";
- 7 Post. ispublished = true;
- 8 Post. iscommentsenabled = false;
- 9 Post. categories. Clear ();
- 10 post. tags. Clear ();
- 11 Post. Save ();
- 12
Copy code
Modify the article:
- 1 post = post. getpost (New GUID (request. querystring ["ID"]);
- 2 Post. Title = "blogengine. NET architecture and source code analysis series Part2: Business Object-common parent class businessbase ";
- 3 Post. content = "xxxxxx ";
- 4 post. Description = "xxxxxx ";
- 5 post. ispublished = true;
- 6 post. iscommentsenabled = false;
- 7 Post. Save ();
- 8
Copy code
Delete an article:
- 1 post = post. getpost (New GUID (request. querystring ["ID"]);
- 2 2 Post. Delete (); // an identifier is actually made inside the object. When saving, the specific deletion will be completed based on the identifier.
- 3 3 Post. Save ();
- 4
Copy code
Obviously, blogengine. net adopts the object-oriented design method, and events and inheritance have been widely used. In addition, it is better used.. NET platform provides models to solve problems, such as the provider model and some interface specifications. In addition, we can see that blogengine. Net has many objects in the memory, and the processing method of exchanging space for time is relatively reliable in such a system.
It is necessary to make some summary.