程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 關於模板中的動態取值,模板動態取值

關於模板中的動態取值,模板動態取值

編輯:C#入門知識

關於模板中的動態取值,模板動態取值


      在項目中經常遇到一個問題,打印word或者打印excel的時候,我們經常使用一對一的賦值或者批量替換的方式來對模板進行修改。

      但是現在遇到兩種場景:

      1、取值是通過自定以方法進行取值的。

       如:一個銷售單據,會涉及到很多種費用,並且這些費用是由後台配置的,非常靈活。但是我們在制作打印模板時取值各項費用我們該如何去定義他呢,如何給他賦值呢?我們如果針對這一個場景下的模板進行一個特殊定義後,在打印另一份單據或者遇到同樣的取值非常靈活的數據,是不是也需要進行特殊處理呢。

      2、取值是通過自行定義進行取值的。

      如:還是一個銷售單據,我們打印的可能是銷售價格,成本、毛利,但是如果我們打印的時候涉及到提成配比,提成配比可能是根據銷售價格算的,可能根據毛利算的,可能根據效益來算的,那麼是不是我們在做這個模板的時候定義:提成(按成本)、提成(按毛利)、提成...。  

     在這中情況下,我的解決方案是采用反射與javascript進行處理:

     這裡大致講述一下我的解決思路,各位過路大神,各位奮戰一線的程序猿們,看過笑過,不喜勿噴~

     第一步:建立兩種Eval方法,來解析表達式

   C#Eval反射式:(此種方式主要應對在程序中自定義的方法,根據參數及方法來模擬程序中的計算,並將結果返回過去,這種方法必須制定處理他的主體Object)

             

/// <summary>
/// CShrapEval 的摘要說明
/// </summary>
public class CShrapEval
{
	 
	 
    /// <summary>
    /// 計算結果,如果表達式出錯則拋出異常
    /// </summary> 
    public static object Eval(string action,Type type,object obj,object[] parm)
    {
        return type.InvokeMember(
                    action,
                    BindingFlags.InvokeMethod,
                    null,
                    obj,
                  parm 
                 );
    }


    public static object Eval(string Cstring, Type type, object obj)
    {
        string action = Cstring.Split('|')[0];
        object[] parm = Cstring.Split('|')[1].Split(',');
        return type.InvokeMember(
                    action,
                    BindingFlags.InvokeMethod,
                    null,
                    obj,
                  parm
                 );
    }
}

  JavaScript腳本編譯方式:模擬javascript工作方式去處理一個表示式,可以使用一個javascript常用函數(如getdate()  length等),靈活方便

 

/**/
/// <summary>
/// 動態求值
/// </summary>
public class JavaEval
{
    /**/
    /// <summary>
    /// 計算結果,如果表達式出錯則拋出異常
    /// </summary>
    /// <param name="statement">表達式,如"1+2+3+4"</param>
    /// <returns>結果</returns>
    public static object Eval(string statement)
    {
        return _evaluatorType.InvokeMember(
                    "Eval",
                    BindingFlags.InvokeMethod,
                    null,
                    _evaluator,
                    new object[] { statement }
                 );
    }
    /**/
    /// <summary>
    /// 
    /// </summary>
    static JavaEval()
    {
        //構造JScript的編譯驅動代碼
        CodeDomProvider provider = CodeDomProvider.CreateProvider("JScript");

        CompilerParameters parameters;
        parameters = new CompilerParameters();
        parameters.GenerateInMemory = true;

        CompilerResults results;
        results = provider.CompileAssemblyFromSource(parameters, _jscriptSource);

        Assembly assembly = results.CompiledAssembly;
        _evaluatorType = assembly.GetType("Evaluator");

        _evaluator = Activator.CreateInstance(_evaluatorType);
    }

    private static object _evaluator = null;
    private static Type _evaluatorType = null;
    /**/
    /// <summary>
    /// JScript代碼
    /// </summary>
    private static readonly string _jscriptSource =

        @"class Evaluator
              {
                  public function Eval(expr : String) : String 
                  { 
                     return eval(expr); 
                  }
              }";
}

  第二步、構建好兩個eval之後我們就需要在程序中去識別那些是C#,那些是javascript代碼斷

      這裡我處理的辦法是:<c ...代碼  /> 和<J ...代碼 />使用這兩種方式分別標示是那種代碼

      然後在處理中我們只需要找出那些是C代碼 那些是J代碼,並且對代碼斷進行計算

    

       public void ExportDoc()
        {
            ExportReplace();
            foreach (NodeTemplate temp in DocTemplateList)
            {
                ExportDoc(temp);
            }
            if (ActionObject != null)
            {
                //動態取值
                ExportDymic();
            }
        }

        //定義C表達式
        System.Text.RegularExpressions.Regex RegexC = new System.Text.RegularExpressions.Regex(@"\<C\w*\|\w*[\,\w*]*\\\>");
        //定義J表達式
        System.Text.RegularExpressions.Regex RegexJ = new System.Text.RegularExpressions.Regex(@"\<J^\>*\\\>");

        //業務邏輯理論為先處理C在處理J,但是C與J由存在循環處理的過程
        public void ExportDymic()
        {
            var MatchesS = RegexC.Matches(doc.GetText());
            foreach (System.Text.RegularExpressions.Match MatchC in MatchesS)
            {
                string Cstring = MatchC.Value.Replace("<C", "").Replace("\\>", "");
                string result = CEval(Cstring);
                //CShrapEval.Eval(Cstring, this.GetType(), this).ToString();
                //A = A.Replace(MatchC.Value, result);
                doc.Range.Replace(MatchC.Value, result, false, false);
            }
            MatchesS = RegexJ.Matches(doc.GetText());
            foreach (System.Text.RegularExpressions.Match MatchC in MatchesS)
            {
                string Jstring = MatchC.Value.Replace("<J", "").Replace("\\>", "");
                string result = JavaEval.Eval(Jstring).ToString();
                doc.Range.Replace(MatchC.Value, result, false, false);
            }
        
        }

        public string CEval(string A)
        {
            var MatchesS = RegexC.Matches(A);
            foreach (System.Text.RegularExpressions.Match MatchC in MatchesS)
            {
                string Cstring = MatchC.Value.Replace("<C", "").Replace("\\>", "");
                string result =  CEval(Cstring).ToString();
                A = A.Replace(MatchC.Value, result);
            }
            MatchesS = RegexJ.Matches(A);
            foreach (System.Text.RegularExpressions.Match MatchC in MatchesS)
            {
                string Jstring = MatchC.Value.Replace("<J", "").Replace("\\>", "");
                string result = JEval(Jstring).ToString();
                A = A.Replace(MatchC.Value, result);
            }
          
           return CShrapEval.Eval(A, ActionObject.GetType(), ActionObject).ToString();
        }

        public string JEval(string A)
        {
            var MatchesS = RegexC.Matches(A);
            foreach (System.Text.RegularExpressions.Match MatchC in MatchesS)
            {
                string Cstring = MatchC.Value.Replace("<C", "").Replace("\\>", "");
                string result = CEval(Cstring).ToString();
                A = A.Replace(MatchC.Value, result);
            }
             MatchesS = RegexJ.Matches(A);
            foreach (System.Text.RegularExpressions.Match MatchC in MatchesS)
            {
                string Jstring = MatchC.Value.Replace("<J", "").Replace("\\>", "");
                string result = JEval(Jstring).ToString();
                A = A.Replace(MatchC.Value, result);
            }
            return JavaEval.Eval(A).ToString();
        }

  

這樣就可以對表達進行精確的解析了,當然目前還有一些未考慮完全的地方 ,待各位看客老爺指點。

好的~今天就貼到這裡, 後期看看被噴的程度來確定是否繼續在博客園發一些日志

  

    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved