CMS system template engine design (3): design of the label base class

Source: Internet
Author: User
The previous section describes the entire production process of the page. We are looking forward to the third article, that is, replacing the label, the core content of production. To be honest, I am very stressed. :) you may not accept it because of a single implementation idea. My tags are divided into two types. One is the configuration variable tag (that is, the config of the site and the System), which is represented by % variable name %. It should be replaced before labels is initialized. The other is the data call label. Take a look at the style: // a simple loop list {Article: List Top = "10" categoryid = "5 "} <A href = "/details/ [Field: Filename/] "Target =" _ blank "> [Field: Title/] </A> {/Article: List} // Reference the user control template. categoryid is the parameter to be passed. {System: Include Templateid = "5" categoryid = "7" /} // Details page template {Article: Model ArticleID =" URL (ArticleID) "} <H1> [Field: Title/] </H1> {/Article: Model} {Artcile: model name = "posttime" Dateformat = "yyyy-mm-dd " /} As you can see, the format is uniform. For me: article: List: Is the list tag top in the article module. : Number of calls categoryid: Category Id also supports other attributes, such as Skip, class, and cache. The key to these attributes is the list tag support. The following <A>... </a> is of course a loop, while [field: fieldname/] is a specific field, followed by a tag closure. For example, the include label of the system module does not contain any content. The field display on the details page is different from the list, and its fields can be placed anywhere. Therefore, the model below can be output even if there is no ID: there are many details about these seven dimensions. How do we interpret these labels? Code What about it? In fact, these are all texts, and code execution relies on reflection. So you have to reflect it! Yes, article is Program Set (or namespace), and list is actually a class. The list contains many parameters and the loop body, so the parameters are actually parameter, and the [field] in the loop body is actually a class (field ). Haha, everything is a class. So, all kinds of labels are classes. We need to abstract their public part as the base class, and maybe we need to design some interfaces? According to all the information we mentioned, the ID, parameters, fields, cache, HTML, and gethtml () methods can be considered currently. From the above labels, we can see that include will pass parameters to the tags in the subtemplate, so parameters should be variable, and fields should also be best variable, so the array is not suitable. In addition, the field must be replaced during the loop, so it is best to use a key-value pair set (K/V) for fields ). Is it appropriate to save parameters as K/V? Save it for the moment. What is the purpose of each tag on a webpage? Convert to HTML, even if it is empty (maybe the output is empty under some conditions), should we design it as a virtual function or abstract it into an interface? First, the significance of virtual functions is that sub-classes can be overwritten, but can also be directly used, while interfaces must be implemented. If an interface is designed to implement more labels without output, it is not annoying. So for the time being, we have designed virtual functions. Maybe our decision is wrong. In addition, gethtml feels that the name is not accurate enough because each label has the original HTML code, so it is renamed getrenderhtml ().
///  /// label base class ///  public class label {///  // ID, the key ///  Public String ID {Get; set ;} ///  /// original HTML code ///  Public String HTML {Get; set ;} ///  /// tag parameter ///  Public idictionary 
  
    parameters {Get; set ;} /// 
    /// tag field ///  Public idictionary 
   
     fields {Get; set ;} /// 
     /// cache ///  Public cache {Get; set ;} /// 
     /// obtain the HTML to be rendered ///  /// 
     
     Public Virtual string getrenderhtml () {return string. empty ;}}
   
  
Do you think parameters and fields are ugly? Because there are still many operations on them (getting a parameter, deleting, adding, enumerating, etc.), they should be encapsulated separately. In case idictionary is inappropriate one day, encapsulation is appropriate. So changed, Public parametercollection parameters {Get; set ;} Public fieldcollection fields {Get; set ;} So how can we find these labels on the page and instantiate them? Of course it is a powerful regular expression. {((? <A> \ W + ):(? <C> \ W + ))(? <P> [^}] *) (/}) | (}(? <T> (?> (? <O> {\ 1 [^}] *}) | (? <-O> {/\ 1}) | (? :(?! {/? \ 1) [\ s]) *) (? (O )(?!)) {/\ 1 })) I want to say: you know :). The string is divided into four components: Assembly, class, parameters, and template. The parametercollection and filedcollection of the label must be obtained from the <parameters> group and <template> group again using regular expressions. Parameter regular :(? <Name> \ W +) = (? <Value> ("([^"] +) ") | ('[^'] + ') | ([^ \ s \}] + )) Field regular: \ [field :(? <Name> [\ W \.] + )(? <Parameters> [^] + )? /\] Let me talk about the nested Implementation ideas: 1. Recursive template: Find all labels and the nested labels must have ID numbers. 2. When replacing the data in each row of the outer label, you need to pass the data dataitem of the current row to the label in the layer. The label instance in the layer can be found through findlabel (ID. Is it a bit like repeater? Haha. 3. The template of the outer label must replace the HTML of the inner label. Otherwise, the field will be messy. If you have said so much, it is better to see the code clearly, then create a labelfactory class to be responsible for label production.

Public class labelfactory {// <summary> // match the regular expression of the label /// </Summary> Private Static readonly RegEx labelregex = new RegEx (@"{((? <A> \ W + ):(? <C> \ W + ))(? <P> [^}] *) (/}) | (}(? <T> (?> (? <O> {\ 1 [^}] *}) | (? <-O> {/\ 1}) | (? :(?! {/? \ 1) [\ s]) *) (? (O )(?!)) {/\ 1 }))"); /// <summary> /// obtain all the labels it contains Based on the template /// </Summary> /// <Param name = "template"> template </param> /// <Param name = "preinit"> work required before label initialization </param> /// <returns> </returns> Public static ilist <label> Find (string template, action <label> preinit) {varMS = labelregex. matches (Template); If (Ms. count = 0) return NULL; var list = new list <label> (); foreach (Match m in MS) {var label = create (M. groups [0]. value, M. groups ["A"]. value, M. groups ["C"]. value, M. groups ["p"]. value, M. groups ["T"]. value); // subscribe to the event if (preinit! = NULL) {label. preinit + = preinit;} // find the sub-label of the label. If yes, the templatestring var labels = find (label. templatestring); If (labels! = NULL) {label. templatestring = label. templatestring. replace (labels [0]. templatestring, String. empty);} // label. init (); list. add (Label); If (labels! = NULL) list. addrange (labels) ;}return list ;}/// <summary> /// reload the preceding find statement. This method is generally used, unless you need to specially process some labels /// </Summary> /// <Param name = "template"> </param> /// <returns> </returns> Public static ilist <label> Find (string template) {return find (template, null );} /// <summary> /// create a label with reflection /// </Summary> /// <Param name = "template"> the original HTML of the label, used to replace the </param> /// <Param name = "A"> Assembly name </param> /// <Param name = "C"> label class name </ param> /// <Param name = "p"> tag parameter </param> /// <Param name = "T"> tag template </param> /// <returns> </returns> Private Static label create (string template, string A, string C, string P, string t) {var Assembly = assembly. load (a); var label = assembly. createinstance (C, true) as label; label. html = template; label. templatestring = T; label. parameterstring = P; return label ;}}
This code is simple, and exceptions are certainly there. I just want to write the code :)
Careful friends will find that the label has added some new content. Yes, it is filled and modified during the design process. It was a normal design process that nobody considered at the beginning. Look at the changes to the label and add several attributes, A preinit event, and an initialization method. The given HTML code contains several labels, so find will return a list, in addition, we also need a create method class to reflect every label. After instantiating a label, you also need to check whether the label is nested with the label, so you need to continue to find the template of the label, so that recursion .. If you can find the label, replace the template of the first label in the parent template. Otherwise, problems may occur during fields initialization.
Why did we design an event?
Because the include label requires passing parameters to the label, you may change the parameterstring and templatestring of the label before the label initialization.

/// <Summary> /// original HTML code /// </Summary> Public String HTML {Get; set ;} /// <summary> /// parameter string of the label /// </Summary> Public String parameterstring {Get; set ;} /// <summary> /// label template /// </Summary> Public String templatestring {Get; set ;} /// <summary> /// events before initialization /// </Summary> public event action <label> preinit; /// <summary> /// initialize label /// </Summary> Public Virtual void init () {If (preinit! = NULL) {preinit (this) ;}// Initialize all parameters = new parametercollection (parameterstring); // Initialize all fields = new fieldcollection (templatestring );}

Well, I 've been writing it for too long. everyone and I are digesting and taking a rest. :) later I will continue to talk about the design of parameters and fields.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.