ASP.NET MVC 框架很好地贯彻了面向接口编程这一设计原则,这使得我们可以很容易替换 MVC 框架中的一些默认实现,比如通过替换默认的依赖解析器,我们可以得到 Controller 中获取依赖对象的控制权,因此便可以决定 Controller 中使用的 Service 接口或 Repository 接口的具体实现。如何决定接口的具体实现是什么?如果初始化对象需要提供构造参数,那么该如何处理依赖?这里面涉及许多枯燥的配对工作和复杂的依赖处理工作,自己实现一套 IoC 容器的代价是巨大的,还好我们有开源的 StructureMap。有很多文章介绍 StructureMap,说它是一个轻量级的 IoC 框架,其实不然,StructureMap 其实是一个代码量大且比较复杂的框架,也许是因为它没有其他第三方依赖,且基础功能使用起来比较简单的关系,使人们产生了这种错觉。
StructureMap 除了一些大多数 IoC 框架都有的一些功能外,还有一些非常强大的特色功能,比如扫描程序集自动匹配子类型,这能够减少许多不必要的配置,此外它还提供了插件系统,通过编写插件可以使应用程序具有高可伸缩性,配合面向切面编程组件可谓是如虎添翼。
刚才说到对于大型应用,后台的任务调度是少不了的,如果把任务放在网站中运行,那将是不可靠的,因为很多情况会导致 iis 应用程序池重启,所以一般情况下将使用 Windows 服务,使用 Topshelf 就是创建 Windows 服务的一种方法,它拥有跨平台特性,相比 .NET 中提供的创建 Windows 服务的 API,它的优势是使用简单且可以从控制台运行,这给开发和调试服务提供了非常大的便利。
从某种角度来说,垃圾信息大致可以分为两类,一类是误导类信息,这一类是人写的,你需要有一定的批判性思维才能避免被误导,而第二类则很好区分,因为它根本就不是人写的,对,不要笑,这可是垃圾信息的一个大源头。不是人写的,也就是说这些信息是由机器产生的,这类信息又分为几类:采集、伪原创、自动翻译等等,这类信息根本就毫无价值,如果说第一类信息还需要稍微动动脑筋才能鉴别出好坏,那这一类简直是不用动脑也能看出来是垃圾信息,那你说这些信息为什么还会存在呢?这不得不说到几个新兴的行业,网络营销和搜索引擎优化,SEO优化有白帽和黑帽之分,所谓黑帽SEO,其实就是钻搜索引擎空子,毕竟搜索引擎也是机器,它对信息质量判断的准确度取决于它的算法,有大量的搞seo优化的人,整天都在想方设法让搜索引擎认为一篇垃圾信息是原创的、高质量的,在他们看来被搜索引擎收录,有排名有流量就有money,所以这背后也是有利益链条存在的。这类垃圾信息的特点就是量大,高质量信息的产生速度怎么可能比的上这些机器自动生成的信息呢,虽然我们可以一眼就看出这类信息不值得阅读,但是当你在搜索时,这些垃圾信息很有可能出现在你的搜索结果里面,它们妨碍了你找到真正有价值的内容,要避免这种情况,我们只能挑选更好的搜索引擎,根据经验使用恰当的关键字。说到搜索信息,那无疑是推荐使用更好的 Google 了,而在国内,因为墙的问题 Google 又经常打不开,所以为了更好的获取信息、不让垃圾信息肆意滋生,我们应该翻墙,信息应该自由的传播。
你是否有过这样的需求——想运行 ASP.NET 程序,又不想安装 IIS 或者 Visual Studio?我想如果你经常编写 ASP.NET 程序的话,应该或多或少都会碰到这种情况。除了使用 IIS 和 VS,我们还有哪些方式可以运行 ASP.NET 程序呢,自己写一个支持 ASP.NET 的 Web 服务器怎么样?NO NO NO,如果你只是想找个这样的工具的话,那完全没必要,我们知道使用 VS 可以运行 ASP.NET 程序,那么我们就可以找出 VS 所调用的程序,将其拷贝到没有 VS 和 IIS 的环境中运行,就能运行 ASP.NET 程序了,安装了 VS 的朋友可以到 C:\Program Files\Common Files\Microsoft Shared\DevServer\ 这个目录里面找找看,这个程序的使用方式如下。
GET /lcomplete/AspNetServer HTTP/1.1
Host: github.com
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.72 Safari/537.36
postdata #可选的消息体
第一行是请求行,该行又分为3个部分,分别是动作、URI 和 HTTP 协议版本,后面的 {key}: {value} 格式的行为报头,如果请求为 post 动作的话,则报头后面的post数据为请求正文,需要注意报头和请求正文之间必需以(回车+换行)分割。
Web 服务器接收到一个请求后,就会将请求解析成上面3个部分,并开始处理应答,响应也由3个部分组成:状态行、响应报头、响应正文,响应报头和正文同样使用进行分割,状态行为HTTP协议版本、状态码、状态描述组成,响应报头与请求报头格式相同,只不过请求报头由服务器解释并处理,响应报头由浏览器解释并处理,最后的响应正文便是我们所熟悉的 HTML。
了解了 HTTP 协议的基础知识后,我们可以很容易地构建出一个支持静态文件的 HTTP 服务器,但是如何处理 ASP.NET 动态内容呢,这就要求我们熟悉 ASP.NET 的 HTTP 架构、管道机制、应用程序生命周期和宿主环境。
ASP.NET 运行时机制
ASP.NET 被特意设计成避免依赖 IIS,它的底层架构采用了管道机制,管道由一系列处理 HTTP 消息的对象组成,每个 HTTP 请求都要经过这些对象,每个对象都执行一些自己职责之内的任务。
要处理 ASP.NET 请求,还需要创建一个应用程序域以托管 HTTP 管道,我们可以使用 ApplicationHost.CreateApplicationHost 方法创建应用程序域,该方法接收3个参数:宿主类型、虚拟路径和物理路径,宿主类型需要跨域应用程序边界,所以需要继承自 MarshalByRefObject 类,并提供与其交互的方法,例如至少要提供一个方法使得可以提交 ASP.NET 请求以进行处理。
了解了 ASP.NET 的运行机制后,再来看看编写 ASP.NET 服务器需要使用到哪些类,首先我们需要使用 ApplicationHost 创建应用程序域以获得处理 ASP.NET 请求的能力,接收到请求后构造 HttpWorkerRequest (该类是抽象类,需要定义它的子类)对象,交由 HttpRuntime 类进行处理,接下来的事情就由 HTTP 管道处理了。
publicvoidStart(){_serverSocket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);_serverSocket.ExclusiveAddressUse=true;_serverSocket.Bind(newIPEndPoint(IPAddress.Any,Port));_serverSocket.Listen(1000);IsRuning=true;Console.WriteLine("Serving HTTP on 0.0.0.0 port "+Port+" ...");newThread(OnStart).Start();}privatevoidOnStart(objectstate){while(IsRuning){try{Socketsocket=_serverSocket.Accept();ThreadPool.QueueUserWorkItem(AcceptSocket,socket);}catch(Exceptionex){Console.WriteLine(ex);Thread.Sleep(100);}}}privatevoidAcceptSocket(objectstate){if(IsRuning){Socketsocket=stateasSocket;HttpProcessorprocessor=newHttpProcessor(_host,socket);processor.ProcessRequest();}}