.net 动态编译解决考勤计算问题_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > .net 动态编译解决考勤计算问题

.net 动态编译解决考勤计算问题

 2013/8/3 19:08:28  miarchen  博客园  我要评论(0)
  • 摘要:由于公司实施SAPHR项目,但是SAPHR对考勤功能真的太弱化了,直接从考勤机上读取的原始打卡记录不能直接传输到HR系统里面,因为SAPHR不能识别那些多余的打卡记录,而且必须把打卡记录进行成组标记(P10,P20),以上标红色的是SAPHR顾问给我的反馈信息。这样以来,必须开发一套算法来把多余的打卡记录进行过滤掉,然后标记上是P10还是P20,这样以来,HR系统在做时间评估时才不会出现异常情况。需求已经明确,那么就是设计开发的问题,要开发该功能,需要用到的资源:1、考勤的排班数据2
  • 标签:.net 解决 编译 net 问题

       由于公司实施SAP HR项目,但是SAP HR对考勤功能真的太弱化了,直接从考勤机上读取的原始打卡记录不能直接传输到HR系统里面,因为SAP HR不能识别那些多余的打卡记录,而且必须把打卡记录进行成组标记(P10,P20),以上标红色的是SAP HR顾问给我的反馈信息。

       这样以来,必须开发一套算法来把多余的打卡记录进行过滤掉,然后标记上是P10还是P20,这样以来,HR系统在做时间评估时才不会出现异常情况。

       需求已经明确,那么就是设计开发的问题,要开发该功能,需要用到的资源:

      1、考勤的排班数据

      2、原始打卡数据

      3、取原始打卡数据的算法

      然后就是确定该功能在我们的外围基础数据平台开发(外围系统是用.net开发的)

     

      由于我们公司的考勤计算方式可能会经常有变化,因为不能把打卡数据的算法写死到代码里面,这样有两种解决方案:1是用侟储过程  2是用动态编译

考虑到以后数据库的迁移问题,最终采取.net动态编译方式来处理该问题

      具体的实现思想如下:

      1、把算法代码存储在数据库表

      2、新建一个计算考勤的静态类,类里面定义一个计算考勤的静态方法,传入参数为两上Table类型,一个为排班表,一个为原始打卡记录表,返回参数也

          为DataTable内型,为计算完成后的结果数据,把该段代码保存在一个静态变量里面。

      3、调用计算方法时,把静态类的代码加上代算法代码编译成动态类。

      4、利用反射技术,调用计算方法,返回结果。

      关键性代码如下:

 

动态编译类:

DynCompiler.cs

class="brush:csharp;gutter:false;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Reflection;
using System.Data;

namespace EDICLibrary
{
    public class DynCompiler:IDisposable
    {

        CodeDomProvider _codeprovide;
        CompilerParameters _parameters; 
        CompilerResults _result = null;
        MethodInfo _method = null;
        Object _instance = null;
       
       
        public DynCompiler()
        {
            _codeprovide = new CSharpCodeProvider();
            _parameters = new CompilerParameters();
            _parameters.GenerateExecutable = false;
            _parameters.GenerateInMemory = true;
            _parameters.ReferencedAssemblies.Add("System.dll");
            _parameters.ReferencedAssemblies.Add("System.Data.dll");
            _parameters.ReferencedAssemblies.Add("System.Xml.dll");
        }

        public bool SourceCompiler(string source, out string outputMsg)
        {
             outputMsg = "";
             StringBuilder sbout = new StringBuilder();
             StringBuilder sb = new StringBuilder();
            if (string.IsNullOrEmpty(source))
            {
                outputMsg = "源代码不能为空!";
                return false;
            }
            else
            {
               
                sb.AppendLine("using System;");
                sb.AppendLine("using System.Collections.Generic;");
                sb.AppendLine("using System.Text;");
                sb.AppendLine("using System.Data;");
                sb.AppendLine ("using System.Xml;");
                sb.AppendLine("namespace JMCompiler");
                sb.AppendLine("{");
                sb.AppendLine("public class DynCompilerHelper");
                sb.AppendLine("{");
                sb.AppendLine("public DataTable Calculate(DataTable dtShiftInfo,DataTable dtTimes)");
                sb.AppendLine("{");
                sb.Append(source);
                sb.Append("}");
                sb.AppendLine("}");
                sb.AppendLine("}");
            }
            _result  =  _codeprovide.CompileAssemblyFromSource(_parameters, sb.ToString());
            if (_result.Errors.HasErrors)
            {
                foreach (string str in _result.Output)
                {
                    sbout.AppendLine(str);
                }
                outputMsg = sbout.ToString();
                return false;
            }
            else
            {
                Type _type = _result.CompiledAssembly.GetType("JMCompiler.DynCompilerHelper");
                _instance = Activator.CreateInstance(_type);
                _method = _type.GetMethod("Calculate",new Type[]{typeof(DataTable),typeof (DataTable)});
                outputMsg = "编译成功";
                return true;
            }

        }

        public object GetReturnResult(List<DataTable> parameters)
        {             

            if (_method == null)
            {
                  throw new Exception ("未进行代码编译");
            }
            return _method.Invoke(_instance, parameters.ToArray());   
        }

        
        #region IDisposable 成员

        public void Dispose()
        {
             _codeprovide = null;
             _parameters = null;
             _result = null;
             _method = null;
             _instance = null;
        }

        #endregion
    }
}

计算考勤类:

AttdCalculate.cs

 public  class AttdCalculate
    {
        /// <summary>
        /// 计算考勤
        /// </summary>
        /// <param name="source">计算考勤算法代码</param>
        /// <param name="dtShiftInfo">排班信息</param>
        /// <param name="dtTimes">原始打卡的数据</param>
        /// <param name="msg">输出信息</param>
        /// <returns>计算后的结果表</returns>
        public static DataTable Calculate(string source, DataTable dtShiftInfo, DataTable dtTimes, out string msg)
        {
            if (string.IsNullOrEmpty(source))
            {
                msg = "考勤计算逻辑不能为空";
                return new DataTable();
            }
            DynCompiler complier = new DynCompiler();
            string output;
            bool result = complier.SourceCompiler(source, out output);
            List<DataTable> lstData = new List<DataTable>();
            lstData.Add(dtShiftInfo);
            lstData.Add(dtTimes);
            if (result)
            {
                msg = "计算成功";
                return (DataTable)complier.GetReturnResult(lstData);
            }
            else
            {

                msg = output;
                return new DataTable();
            }
        }           
        
    }

考勤调用代码

 

  //计算公式
                string Source = string.Empty;
                //获取计算工式
                Source  = <获取计算工式的方法>                 
                string msg;
                //获取考勤数据
                
                DataTable dtResult = MIS.Util.AttdCalculate.Calculate(Source, dtShiftInfo, dtTimes, out msg);

 

在写这篇文章的时候,开发的功能还没有投入到正式运行,但是经过最近一段时候的测试来看,没有任何问题。

 

上一篇: ssh+ajax 下一篇: JDK环境配置
发表评论
用户名: 匿名