你的位置:首页 > ASP.net教程

[ASP.net教程].Net Web产品中增加自己的功能和代码?


背景:

最近有一个项目,一个朋友找了一个网上比较成熟的CMS系统(动易),让我给他增加一些功能,这个产品功能挺多,但是没有源代码。按照以前的做法,就是直接反编译他的dll,生成源代码,然后在源代码的基础上修改和完善自己的功能。但是研究了一下这个产品,bin下面的DLL非常多,有主要的,还有辅助的。如果每个dll都反编译,简直不现实。

 

用发编译工具 ILSpy打开里面几个主要的dll,发现还加壳混淆了,用De4Dot反混淆出来。里面的代码还是非常清晰,但是如果每个dll都这样搞,岂不累死。

 

解决办法:

一个web工程有一个主要的dll,其他的都是辅助dll,主要dll依赖于辅助dll。我可以自己建立一个dll,引用辅助dll。然后再让他的主dll调用我的dll。(这里是有前提,他的dll之间没有强命名保护,如果有,也不能直接用,需要把他们的强命名保护去掉才能这样使用)

 

开始步骤:

第一步,新建一个空白模块(DLL模块,或者WEB模块,建议是WEB,因为可能会增加页面),里面需要写我们的一些功能和方法。

第二步,打开新工程的目录,把别人的系统程序(WEB根目录)复制到工程下面(注意,是复制文件夹到来一个工程的文件夹里面,全部覆盖,不是直接拷贝VS工程里面,两者是有区别的)。

第三步,然后回到工程里面,点击"刷新","显示所有文件"。

是不是所有的文件都进来了,这里切记一点,不能把别人的文件包含到这个工程中,必须排除掉。

第四步,引用dll下面所有的辅助dll,这个你需要明白,他的主dll你不能引用,你一定要找对了。

你的工程和人家的dll使用的.net framework必须保持一致,人家是2.0 你也必须是2.0,原理你们应该明白。

 

第五步,可以开始增加我们的程序和功能了。

我们假设他的一个页面的功能有问题,我们如何去修改这个功能,如果他的页面有些数据没有提取出来,我们怎么直接去提取数据。当然,我们可以直接在aspx页面中增加数据库操作的代码直接读取,但是这样的话,可能就跟他的一些程序完全脱节,比如,我们应该共享session,cookies,还有一些全局变量和方法,这样可以重复利用,而不用全新在aspx页面去写这些方法。第四步去引用别人的dll,也是为了达到他的资源最大化使用,他有的,我们尽量不要去写,他没有的,我们可以去写,但是也要跟他保持一个整体。

 

一个简单的例子,想给一个内容页面增加手机分享的功能(手机分享能够正确显示分享标题 图片 和描述)。对应的地址页面是/item/数字.aspx。这个地址一看就知道是一个伪地址。他的真实地址是/item.aspx?id=数字。

我们打开item.aspx看看里面的内容。

 

你发现这个页面什么没有,你以为可以在这个里面写代码,你发现你写的任何代码都不会显示出来的。

因为这个页面的所有信息都是后台模板解析,然后输出来的,如果在这个页面写上静态内容,你看看他是否输出?

当你通过浏览器执行这个页面的时候,你发现并没有您的内容输出。那如果加page_onload呢?是否会执行,你会发现,肯定不会执行,也不会输出任何东西,还是通过 ILSpy去看看别人的源代码吧。

原来,他在onload之前的一个方法就已经response.end(默认为true)了,这样线程终止,也就不会执行到你的方法了。看看他的事件是什么。

可以看出,他执行了页面最顶端的事件PreInit.然后在结尾的时候直接End 终止线程了。

 

那要执行我们的代码,就必须在他之前,再找到一个事件,这样才会执行我们的方法

通过Asp.net 页面生命周期:从OnPreInit到End Render一文,我们可以看到。在他之前确实还有方法DeterminePostBackMode

通过测试,我们的"测试"文本输出到他的内容之前。

 

下面开始演示如何调用我们的工程dll方法

 

一种做法,就是直接通过

嵌入方法,这个方法动态编译并执行。这种方法可能很多人都会,我需要说的来另外一种,通过反射调用我们的dll。

 

第二种做法,我们在lib/fun.cs中写下如下代码

这里需要注意三个问题,第一个是fun.cs 不能包括到项目工程中,第二个问题,就是函数的第一个参数,第一个参数的作用就是缓存动态创建的对象。第三个问题。为什么动态加载程序集的时候要用流的方法。一一告诉大家,都是有原因。

 

第一个fun.cs不包括到工程是能理解的。因为他作为别人产品的一部分,而不是我得产品一部分。

第二个obj参数问题,用于缓存动态创建的事例,为什么不可以每次都创建一个事例得了?

第三个 加载程序集的方法是file.load。但是这种加载不容易释放,编译的时候会经常出现dll正在被使用,第二个,如果每次都加载,会照成dll重复使用。如果里面存在序列化和反序列化,可能会出现转换问题。这也是回答第二个问题。

 

那我们这个缓存的对象放到什么地方,只要是static即可,你可以放到global.ascx中,也可以放到其他aspx页面中。

 

execute方法是通过反射,调用我们dll中weixin这个内里面的方法,所以,我们可以在这个内里面写任意的公共方法,但是要符合我们调用的规则即可。

 

稍后继续。