首页 > 编程 > JavaScript > 正文

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

2019-11-17 02:20:26
字体:
来源:转载
供稿:网友

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

在项目中经常遇到一个问题,打印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();        }

  

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

好的~今天就贴到这里, 后期看看被喷的程度来确定是否继续在博客园发一些日志


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表