下载安卓APP箭头
箭头给我发消息

客服QQ:3315713922

NET类型底层开发技术

作者:课课家教育     来源: http://www.kokojia.com点击数:826发布时间: 2019-03-11 13:59:46

标签: NET技术开发

  一直用.NET做ERP/MIS类型的软件,学业不精,可以完成工作任务,业余时间也制作一些集成化的工具包,下面分享一下我认为的.NET领域里的底层技术。参加工作已经有五年了。由于是非计算机科系,一开始的工作是做网页,维护ASP脚本程序,有时候也要做图片,总而言之,一项任务交到手里,没有借口说不会做,想办法弥补然后把任务做完。后来才得到机会,参与编程开发工作。而且,当时一心想用C#.NET做开发,不希望参与DELPHI的开发,偏偏工作经过层层的转发,交到手里的就是DELPHI开发。经历努力,再后来就真的用.NET进行开发工作,一直持续到现在。消极的观念会说,学的很杂,做的也杂,积极一点的想法,把老板交给你的任务完成,就是称职的员工。现在正值毕业生找工作的时间,一时找不到开发的工作,也不要急,先听从公司的安排做个软件测试,或是文档管理之类的职位,等有空缺的开发人员的机会,你再毛遂自荐,同样可以进入程序员这个领域。机会是留给有准备的人的,难道不是吗?

  一直用.NET做ERP/MIS类型的软件,学业不精,可以完成工作任务,业余时间也制作一些集成化的工具包,下面分享一下我认为的.NET领域里的底层技术。

  1通信技术(Remoting,WCF,ASMX)

  通常的三层架构,数据库,数据访问层,界面层。通讯技术定义了三层组件之间的调用约定,以及方法。这样说起来有些抽象,举例为证。现在要制作一个进销存项目,基本的功能是进仓,出仓,转仓,查询功能要能查询到仓库进出日记帐,

  库存余额。对于一笔物料为FLEX0901的进仓业务,用ORM的方式完成,伪代码如下

  InventoryMovmentEntityreceipt=newInventoryMovmentEntity(“REF1108080001”,"RECEIPT”);

  InventoryMovmentDetailEntitydetail=receipt.InventoryMovmentDetails.AddNew();

  detail.ItemNo=”FLEX0901”;

  detail.MoveDate=DateTime.Now;

  InventoryMovementDAL.Instance.Save(receipt);

  这里有几个问题处理的不错,比如

  1)ORM的数据读写,关注面从拼凑SQL读写到构建实体,这是进步。如果用DAL+SQLScript的方式完成,伪码如下

  stringMySQL=”INSERTICMOVH(RefNo,Direction)VALUES(‘REF1108080001’,'RECEIPT’)";

  InventoryMovementDAL.Instance.ExecuteNonQuery(mySql);

  mySql=”INSERTICMOVD(ItemNo,MoveDate)VALUES(‘FLEX0901’,'2011/8/8’)";

  InventoryMovementDAL.Instance.ExecuteNonQuery(mySql);

  这里省略了拼凑参数值的句段,直接把值放到SQL语句中去。

  后一种方式,明显的缺陷时,当添加新的字段,对系统扩展时,修改和维护起来的成本,明显大于前者。

  2)使用了单件模式,InventoryMovementDAL.Instance来统一操作数据读写,而不是这样

  InventoryMovementDALinventoryDAL=newInventoryMovementDAL();

  inventoryDAL.Save(receipt);

  从这个单件模式,引出了通讯技术的必要性。当有很多个用户,同时操作进仓功能,意味着同时有很多个InventoryMovementDAL的数据写入操作,这时产生的问题

  ◆不好控制前后两张单据的进仓单参考编号重复。为保证不重复,在保存之前,我们需要到数据库检查一次是否已经存在该参考编号的进仓单,也就是InventoryMovementDAL的Save方法的开头,

  要包含这样一段代码,以DAL+SQLScript的方式表示

  tringmySql=”SELECTCOUNT(1)FROMICMOVHWHERERefNo=’REF1108080001’";

  boolexisting=InventoryMovementDAL.Instance.ExecuteScalar(mySql)>0;

  可以想像,当并发用户为100时,每一笔进仓业务,需要预先一次数据检查,来回于数据库,这样的程序性能肯定不好。

  ◆对于库存报表,多个并发的InventoryMovementDAL会导致数据前后不统一。库存余额报表现在可以读到物料FLEX0901还有100个pc,一会当有进仓单入库200pc的FLEX0901时,如果不手动刷新数据,此时的报表仍然显示的物料FLEX0901的库存余额是100,而不是300.这有时候是不可接受的结果。

  可以做一个timer,定期刷新库存余额。这里的问题是,InventoryMovementDAL只有一个实例,无法自己告诉自己,已经有新的库存了,重新读取数据。这里需要一种并发机制,告诉InventoryMovementDAL实例,有新的数据加入到库存余额中,需要刷新报表。

  ◆有一些数据项,是全局的,对于整个系统都是唯一的,需要特殊处理。

  比如ERP系统允许的并发用户,同时允许有10个用户连接进入系统,超过则无法处理;

  ERP系统的一个用户把当前系统的默认货币从HK$改进了US$,其它的用户,要能知道这个改变,此时,不太可能让当前正在操作业务的用户退出,重新进入系统;

  当发生网络故障时,ERP系统要能知道网络故障,并suspend当前正在进行的操作;这一点可以理解为一条有效的改善,当无法连接到SQLServer时,要阻止当前正在录入数据的用户,否则他很辛苦的录入了数据,而系统又无法保存,给出一个提示Anetwork-relatedorinstance-specificerroroccurredwhileestablishingaconnectiontoSQLServer.TheserverwasnotfoundorwasnotAccessible.VerifythattheinstancenameiscorrectandthatSQLServerisconfiguredtoallowremoteconnections用户会抱怨你的软件没有做好,尽管这不是你的错。

  如下图,当前用户正在编辑客户资料,发生网络故障,界面被Disable了。借助于通讯技术中的并发,可以实现。NET_技术开发_通信技术_代码介绍_课课家

  通篇都没有给Remoting,WCF打广告,说Remoting,WCF的好处。当你的程序遇到这几个问题时,是否可以考虑下通讯技术,来改善性能和客户体验。

  2反射,动态编译

  反射是动态获取程序集的元数据的一种技术,这句话是做.NET程序员面试题目的一个的答案,你可选择记住它,就好比高中生物学里面讲到的细胞的结构的课程时,细胞由细胞膜,细胞质和细胞核组成。根据做程序的经验,Neveraskwhy不是好习惯,即使是微软的API,有时候违反了调用约定,也会很抓狂。

  请看下面这一段代码

  Assemblyassembly=Assembly.GetExecutingAssembly();

  objectentryForm=Activator.CreateInstance(formBaseType)asForm;

  entryForm.MdiParent=this;

  entryForm.Show();

  entryForm.Activate();

  代码的含义比较简单,从当前程序集中创建formBaseType类型,并调用它的方法。从方法名上来看,大概可以看出,这是一段MDI创建child子窗体,并显示子窗体的代码。

  这段小代码,也是插件式框架的基本思路,请参考《ManagementConsole工具管理类软件通用开发框架(开放源码)》中的例子来体会它的用处。

  在ERP/MIS系统中,应用反射的例子,实在是太多了。数据访问接口InventoryMovementDAL,借助于反射,来查找并调用它的实现类;窗体也它的子窗体借助于反射来获取属性,传递值;ERP系统的整个框架,也是借助于反射搭建起来.

  看下面的图,ERP的三个模块Paradox.ERP.SystemAdministration,Paradox.ERP.Engineering,Paradox.ERP.Inventory被Paradox.Framework.Kernal反射调用,如果再写一个Paradox.ERP.Sales的销售模块,几乎不需要改动,就可以让它被框架调用。

  动态编译的例子,是应用到一个工资系统中.请看图

  对于如何解析工资的formular公式,有若干种办法,这里使有的是动态编译的方法。把每一个工资项看成是一个类型class的属性,Formular的内容则放到一个方法中去,当成表达式计算求职,最后应用反射,返回各属性的值即可。

  publicclassFormularCalculation

  {

  publicstaticobjectBuild(string[]items,stringformular)

  {

  stringnameSpace="A";

  stringclassName="FormularCalculation";

  stringmethodName="Run";

  CSharpCodeProvidercompiler=newCSharpCodeProvider();

  CompilerParametersparas=newCompilerParameters();

  paras.GenerateExecutable=false;

  paras.GenerateInMemory=true;

  StringBuilderclassSrc=newStringBuilder();

  classSrc.Append("usingSystem;"+Environment.NewLine);

  classSrc.Append("namespace"+nameSpace+"{"+Environment.NewLine);

  classSrc.Append("publicclass"+className+"{"+Environment.NewLine);

  foreach(stringiteminitems)

  {

  classSrc.Append("publicdecimal"+item+";"+Environment.NewLine);

  }

  classSrc.Append("publicvoidRun(){基本工资=5000;"+Environment.NewLine);

  string[]format=Regex.Split(formular,Environment.NewLine);

  foreach(stringpropinformat)

  {

  classSrc.Append(prop+";"+Environment.NewLine);

  }

  classSrc.Append("}"+Environment.NewLine);

  classSrc.Append("}"+Environment.NewLine);

  classSrc.Append("}"+Environment.NewLine);

  stringsource=classSrc.ToString();

  CompilerResultsresult=compiler.CompileAssemblyFromSource(paras,source);

  CompilerErrorCollectionerror=result.Errors;

  Assemblyassembly=result.CompiledAssembly;

  objecteval=assembly.CreateInstance(nameSpace+"."+className);

  MethodInfomethod=eval.GetType().GetMethod(methodName);

  objectreobj=method.Invoke(eval,null);

  returneval;

  }

  }

  调用方法如下

  string[]items={"应发合计","基本工资","奖金","福利费","扣款合计","社保","税","实发合计","应税所得额"};

  stringformular=@”应发合计=基本工资+奖金+福利费-扣款合计;

  扣款合计=社保+税+应税所得额;

  实发合计=应发合计-扣款合计;";

  objectobj=FormularCalculation.Build(items,formular);

  Typetype=obj.GetType();

  foreach(PropertyInfofiintype.GetProperties(BindingFlags.NonPublic|BindingFlags.Public

  |BindingFlags.Instance|BindingFlags.DeclaredOnly))

  {

  stringvalue=fi.Name;//取到计算后的各个属性的值

  }

  动态编译还应用于软件的加密,在内存中产生加密程序的源代码,动态编译并运行,检测是否符合license授权。

  3ORM(NHibernate,LLBLGen)对象关系映射

  虽然可以找出很多理由来拒绝ORM,比如performance不好,接口不好用,没有NHibernate设计器,是的,这都是理由。但是,一旦接触过ORM之后,我发现做系统再也离不开这个工具。相对于ERP/MIS类的系统,大部分时间都是和SQL的读写在搏斗,ORM带给你的几个好处,是不可忽视的。

  1)增加或删除数据库字段,界面和程序几乎不需要改动。这一点我非常认同,即使是很稳定的系统,也避免不了要做customization,也要加些字段,如果用SQL拼凑,你几乎要改动所有的相关内容,而且还无法获取编译器的语法检查的好处,ORM在编译期间就可以检测出一些类型不匹配的问题。

  2)界面和逻辑的真正分离改动计算逻辑,不需要改动界面,也就是实现MVC,MVP的模式,其实我们可以不用管这两个模式,我们只是在用ORM来读写数据库。

  3)代码更幽雅,调试起来更容易,维护方便。

  Linq技术之后,微软大力发展EntityFramework,不推荐在项目中使用。MS的优点是,它发现一项技术很有用,或为开发一个很得力的工具,最终它会做的很好,比如VisualStudio,Office,但是这是需要时间的,它要不停的学习,观察,改善,特别像API这类的东西,如果更新太快,会对项目产生较大的风险,实际项目中最需要的是稳定的API。MS打算要放弃的东西,它会慢慢减少资源,慢慢减少关注的次数,时间一长,最后就淡出了开发人员的视线。

  NHibernate经过多年的发展,稳定,好用,有庞大的java社区(Hibernate)的支持,不愁遇到问题没有答案。

  4工作流Workflow

  目前微软推出了两个版本的工作流,.NET3.5和.NET4.0的,应该把它看成两个产品,并不是简单的版本升级。

  ERP/MIS领域常见的需求有

  1)采购单审批(如果条件)要求:

  当金额大于等于500且采购员为A时,需要通过May的审批

  当金额大于等于500且采购员为B时,需要通过Jack的审批

  当金额小于500时,不需要通过审批,可直接过帐

  2)当发生工程更改ECN时,要通知生产部重排计划,通知货仓安排发料。

  像这种类型的需求,每个企业的要求都不一样,要达到定制的目的,又不想为每个不同的客户分别写代码,非用到工作流不可。你可以不选择用工作流,那就为不同的客户定制代码,也行。

  MS的工作流也做成了中间件,你需要尽可能的override。

赞(0)
踩(0)
分享到:
华为认证网络工程师 HCIE直播课视频教程