关于模板中的动态取值 ---反射与javascript脚本编译

在项目中经常遇到一个问题,打印word或者打印excel的时候,我们经常使用一对一的赋值或者批量替换的方式来对模板进行修改。

      但是现在遇到两种场景:

      1、取值是通过自定以方法进行取值的。

       如:一个销售单据,会涉及到很多种费用,并且这些费用是由后台配置的,非常灵活。但是我们在制作打印模板时取值各项费用我们该如何去定义他呢,如何给他赋值呢?我们如果针对这一个场景下的模板进行一个特殊定义后,在打印另一份单据或者遇到同样的取值非常灵活的数据,是不是也需要进行特殊处理呢。

      2、取值是通过自行定义进行取值的。

      如:还是一个销售单据,我们打印的可能是销售价格,成本、毛利,但是如果我们打印的时候涉及到提成配比,提成配比可能是根据销售价格算的,可能根据毛利算的,可能根据效益来算的,那么是不是我们在做这个模板的时候定义:提成(按成本)、提成(按毛利)、提成...。  

     在这中情况下,我的解决方案是采用反射与javascript进行处理:

     这里大致讲述一下我的解决思路,各位过路大神,各位奋战一线的程序猿们,看过笑过,不喜勿喷~

     第一步:建立两种Eval方法,来解析表达式

   C#Eval反射式:(此种方式主要应对在程序中自定义的方法,根据参数及方法来模拟程序中的计算,并将结果返回过去,这种方法必须制定处理他的主体Object)

             

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/// <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等),灵活方便

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/**/
/// <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代码,并且对代码断进行计算

    

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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();
  }

  

这样就可以对表达进行精确的解析了,当然目前还有一些未考虑完全的地方 ,待各位看客老爷指点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值