
作者: 左其盛 发表于 2010-07-18 22:30 原文链接 阅读: 131 评论: 0
最近在做的一个项目遇到这么一个问题:需要把一个字符串格式的卡号转换为bigint格式的卡号。t-sql自带的isnumeric函数不能用。它认为合格的数字不一定是bigint,比如一些带小数点的数字,科学计数的数字。上网搜,中文资料中没发现有帮助的,在sqlservercentral上发现有人写过这个函数了。关键的算法就是charindex + substring循环,一个一个看有没有不合法的字符。文章的评论中有人说可以用patindex函数,更快。不过用了这两个都解决不了全角数字的问题,他们都认为全角数字是合法的数字,当然实际转换为bigint的时候会报错。
又上网搜了搜,注意到了COLLATE关键字。一般的解释是它可以指定排序规则。可以改变的规则有大小写、重音、假名(日语才有)、全角半角。中文系统中很少用到这个关键字。一般就用默认的大小写不敏感。我这里想区分全角半角,必须用COLLATE关键字。可以这么用:charindex(substring(@s, @i, 1), '0123456789' COLLATE Chinese_PRC_CS_AS_KS_WS),其中COLLATE后面的参数中Chinese_PRC指定字符集所使用的代码页(其实就是所用的语言),后面最多可以跟四个×s,S表示敏感,对应的I表示不敏感。比如Chinese_PRC_CS_AS_KS_WS表示是简体中文,大小写敏感(CS),重音敏感(AS,这个对汉语没意义),区分假名类型(KS,这个对汉语也没意义),区分全角半角(KS),Chinese_PRC_CI_AI表示简体中文,大小写不敏感,重音不敏感,不区分假名类型,不区分全角半角。后两个参数忽略掉就表示否定。当然还可以直接指定二进制排序,全角半角的问题就自然解决了,而且二进制排序还更快一些:charindex(substring(@s, @i, 1), '0123456789' COLLATE Chinese_PRC_BIN)
因此,理论上这个判断字符串是否为bigint的问题的核心算法有四种解决方案:
charindex(substring(@s, @i, 1), '0123456789' COLLATE Chinese_PRC_CS_AS_KS_WS)
charindex(substring(@s, @i, 1), '0123456789' COLLATE Chinese_PRC_BIN)
patindex('%[^0-9]%',@s COLLATE Chinese_PRC_CS_AS_KS_WS )
patindex('%[^0-9]%',@s COLLATE Chinese_PRC_BIN )
不过实验发现第三种不能解决问题,仍然认为全角数字是合法的数字。看微软msdn文档,上网搜都没有找到答案。其他三种都可以。理论上最后一种最快。
下面是完整的函数的代码:
/*
-- Tests pass isnumeric AND fail IsBigInt AND fail cast(vc as bigint)
-- range
SELECT IsNumeric('-9223372036854775809'), dbo.IsBigInt('-9223372036854775809')
SELECT IsNumeric('9223372036854775808'), dbo.IsBigInt('9223372036854775808')
-- invalid chars
SELECT IsNumeric('-5d2'), dbo.IsBigInt('-5d2')
SELECT IsNumeric('-5e2'), dbo.IsBigInt('-5e2')
SELECT IsNumeric('+3,4'), dbo.IsBigInt('+3,4')
SELECT IsNumeric('+3.4'), dbo.IsBigInt('+3.4')
-- pass this strange case
SELECT IsNumeric('00000000000000000000000000001'), dbo.IsBigInt('00000000000000000000000000001')
*/
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'dbo.IsBigInt') AND type IN (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION dbo.IsBigInt
GO
CREATE FUNCTION dbo.IsBigInt (@a varchar(30))
returns bit
AS
BEGIN
-- Submitted to SqlServerCentral by William Talada
DECLARE
@s varchar(30),
@i int,
@IsNeg bit,
@valid int
-- assume the best
SET @valid = 1
SET @IsNeg=0
SET @s = ltrim(rtrim(@a))
-- strip OFF negative sign
IF len(@s) > 0
AND LEFT(@s, 1) = '-'
BEGIN
SET @IsNeg=1
SET @s = RIGHT(@s, len(@s) - 1)
END
-- strip OFF positive sign
IF len(@s) > 0
AND LEFT(@s, 1) = '+'
BEGIN
SET @s = RIGHT(@a, len(@a) - 1)
END
-- strip leading zeros
while len(@s) > 1 and left(@s,1) = '0'
set @s = right(@s, len(@s) - 1)
-- 19 digits max
IF len(@s) > 19 SET @valid = 0
-- the rest must be numbers only
--SET @i = len(@s)
--WHILE @i >= 1
--BEGIN
----IF charindex(substring(@s, @i, 1), '0123456789' COLLATE Chinese_PRC_CI_AS_WS ) = 0 SET @valid = 0
-- IF charindex(substring(@s, @i, 1), '0123456789' COLLATE Chinese_PRC_BIN ) = 0 SET @valid = 0
-- SET @i = @i - 1
--END
--if patindex('%[^0-9]%',@s COLLATE Chinese_PRC_CI_AS_WS )>0
if patindex('%[^0-9]%',@s COLLATE Chinese_PRC_BIN )>0
set @valid=0
-- check range
IF @valid = 1 AND len(@s) = 19
BEGIN
IF @isNeg = 1 AND @s > '9223372036854775808' SET @valid = 0
IF @IsNeg = 0 AND @s > '9223372036854775807' SET @valid = 0
END
RETURN @valid
END
go
最新新闻:
· 微软不为外界所知的十件趣事(2010-07-18 22:58)
· 中国第2季搜索引擎市场规模达26亿 百度破70%(2010-07-18 22:54)
· Facebook用户数下周达5亿 邀请用户共享故事(2010-07-18 22:49)
· 开源的可视化编辑器 KindEditor 3.5.1 发布(2010-07-18 22:35)
· WordPress 陷入开源‘边界’之争(2010-07-18 17:47)
编辑推荐:揭秘Facebook背后的那些软件

作者: virus 发表于 2010-07-18 21:47 原文链接 阅读: 275 评论: 0
题外话
又是一本Head.First系列的书,这个系列很多,包括:SQL、设计模式、C#、面向对象分析与设计、软件开发等。里面的语言生动活泼,很好的以故事的形式引出正文,而不是枯燥的文字。
书中开篇的建议
1、放慢速度。理解的越多,需要记忆的越少。
不要只是读,要停下来思考。当书中出现一个问题的时候,不要着急浏览答案,假设真的有人问你这个问题。你强迫你的大脑思考的越深,越是你学习和记忆的好机会。
2、做练习。写读书笔记。
不要只是看练习。拿起纸笔。大量的证据表明,学习时候的物理活动可以增加学习的效果。
3、不要跳着读
有一些内容会让你觉得没有太大的用处,其实他们都是内容的一部分,不要跳过他们。这不是可有可无的旁注。
4、确保这是你上床之前的最后一件事,或者至少是最后一件有挑战的事
学习的一部分,尤其是需要长期记忆的,通常在你放下书之后会在大脑中发生,这时候你的大脑需要自己的时间去做更多的处理。如果你在这段处理的过程中又放入新东西,你刚才学的一些内容会丢失。
5、喝大量的水
你的大脑在一个流动的液体中会工作的更好。脱氢胆固醇会降低认识能力,脱氢胆固醇在你感觉渴的时候会产生。
6、大声的说出来
说话时大脑的另一部分。如果你正在理解一些东西,或者想要在一会想起来什么东西,可以大声的讲出来。可以向其他人大声的解释它。你将会学的更快。
7、听从你的大脑
要注意你的大脑负荷是否已经过载。如果你发现自己开始忘记刚才读过的内容,是该休息的时候了。
8、Feel something
your brain needs to know that this matters.Get involved with the stories. Make up your own captions for the photos.
9、设计一些东西
将你读到的新东西进行自己的设计,或者是重新设计以前的东西。
正文
对于什么是好的软件,通常会有不同的意见。因为站的角度不同,关注点不同,得出的结论就会不同。
用户友好的程序员说:
好的软件通常会做用户想要它做的事情。因此,即使用户想以一种新的方式使用它,它也不应该挂掉或者是给出一个不在预期的结果。
面相对象的程序员说:
好的软件的代码应该是面向对象的,因此不应该有一群重复的代码,每一个对象应该很好的控制自己的行为。应该很容易扩展,因为你的设计是可靠并且灵活的。
设计大师说:
好的软件就是使用可靠的设计模式和原则。保持对象的松散耦合,代码对扩展开放,对修改关闭。保持代码的重用性。
轻松使用三步达到好的软件
- 保证你的软件做了用户想要做的事情。
- 应用基本的OO设计原则来增加灵活性。
- 追求一个可维护,可重用的设计。
为了证明什么是有缺陷的,下面是一些原则,可以帮助你找出不匹配的对象类型:
- 对象应该做和他们的名字相符的事情。如果一个对象叫做Jet,他应该会takeOff()和land(),不应该有takeTicket(),这很有可能是另外一个对象的任务,而不属于Jet。
- 每一个对象应该只代表一个概念。不应该让一个对象有两个或者三个职责。避免Duck对象代表木头鸭子,又代表橡皮鸭子。
封装允许你将应用按照不同的逻辑分组。
最新新闻:
· 微软不为外界所知的十件趣事(2010-07-18 22:58)
· 中国第2季搜索引擎市场规模达26亿 百度破70%(2010-07-18 22:54)
· Facebook用户数下周达5亿 邀请用户共享故事(2010-07-18 22:49)
· 开源的可视化编辑器 KindEditor 3.5.1 发布(2010-07-18 22:35)
· WordPress 陷入开源‘边界’之争(2010-07-18 17:47)
编辑推荐:揭秘Facebook背后的那些软件

作者: 麒麟 发表于 2010-07-18 19:58 原文链接 阅读: 631 评论: 9
在Asp.net MVC中,我们能非常方便的使用Ajax。这篇文章将介绍三种Ajax使用的方式,分别为原始的Ajax调用、Jquery、Ajax Helper。
首先看一下原始的Ajax的调用的
在Asp.net MVC中添加一个custom_ajax.js,加入下面使用ajax的脚本代码
function getXmlHttpRequest() { var xhr; //check for IE implementation(s) if (typeof ActiveXObject != 'undefined') { try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } } else if (XMLHttpRequest) { //this works for Firefox, Safari, Opera xhr = new XMLHttpRequest(); } else { alert("对不起,你的浏览器不支持ajax"); } return xhr; } function getMessage() { //get our xml http request object var xhr = getXmlHttpRequest(); //prepare the request xhr.open("GET", "get_message.html", true) //setup the callback function xhr.onreadystatechange = function() { //readyState 4 means we're done if(xhr.readyState != 4) return; //populate the page with the result document.getElementById('result').innerHTML = xhr.responseText; }; //fire our request xhr.send(null); }
在View中引入此脚本,并添加触发的代码:
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> 第一种方式 </asp:Content> <asp:Content ID="Content3" ContentPlaceHolderID="headContent" runat="server"> <script src="http://www.cnblogs.com/Scripts/custom_ajax.js" type="text/javascript"></script> </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <p><strong>点击按钮处罚一个Ajax请求: </strong> <button type="button" onclick="getMessage()">Get the Message</button> </p> <div id="result"></div> </asp:Content> 效果如下:
触发之前:
触发之后:
第二种方式,利用Jquery:这里实现一个最简单的留言板,数据存储在一个List<string>中。在View中引用Jquery:<script src="http://www.cnblogs.com/Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
添加下面脚本:
<script type="text/javascript"> //execute when the DOM has been loaded $(document).ready(function () { //wire up to the form submit event $("form.hijax").submit(function (event) { event.preventDefault(); //prevent the actual form post hijack(this, update_sessions, "html"); }); }); function hijack(form, callback, format) { $("#indicator").show(); $.ajax({ url: form.action, type: form.method, dataType: format, data: $(form).serialize(), completed: $("#indicator").hide(), success: callback }); } function update_sessions(result) { //clear the form $("form.hijax")[0].reset(); $("#comments").append(result); } </script>
创建控制器:public class CommentController : Controller { private IList<string> _comments = new List<string>(); public ActionResult Index() { return View(_comments); } public ActionResult IndexAjaxHelp() { return View(_comments); } public ActionResult AddComment(string comment) { _comments.Add("<li>" + comment + "</li>"); return Content(string.Join("\n", _comments.ToArray())); } }
创建View表单:<h4>Comments</h4> <ul id="comments"> </ul> <% using (Html.BeginForm("AddComment","Comment",FormMethod.Post,new {@class="hijax"})) { %> <%= Html.TextArea("Comment", new{rows=5, cols=50}) %> <button type="submit">Add Comment</button> <span id="indicator" style="display:none"><img src="http://www.cnblogs.com/content/load.gif" alt="loading..." /></span> <% } %>
效果:
第三种方式:Ajax Helper。将最简单的留言板修改成Ajax Helper的方式。
1、首先了解一下Ajax Helper下面四种方法。
a、Ajax.ActionLink():它将渲染成一个超链接的标签,类似于Html.ActionLink()。当它被点击之后,将获取新的内容并将它插入到HTML页面中。
b、Ajax.BeginForm():它将渲染成一个HTML的Form表单,类似于Html.BeginForm()。当它提交之后,将获取新的内容并将它插入到HTML页面中。
c、Ajax.RouteLink():Ajax.RouteLink()类似于Ajax.ActionLink()。不过它可以根据任意的routing参数生成URL,不必包含调用的action。使用最多的场景是自定义的IController,里面没有action。
d、Ajax.BeginRouteForm():同样Ajax.BeginRouteForm()类似于Ajax.BeginForm()。这个Ajax等同于Html.RouteLink()。
这个例子中使用Ajax.BeginForm(),下面具体了解Ajax.BeginForm()的参数。看下面代码
<% using (Ajax.BeginForm("AddComment", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "comments", InsertionMode = InsertionMode.InsertAfter })) { %>
actionName:AddComment(action的名字)
controllerName:CommentController(Controller的名字)
ajaxOptions:
HttpMethod:Ajax的请求方式,这里为POST
UpdateTargetId :Ajax请求的结果显示的标签的ID,这里为comments
InsertionMode:将Ajax结果插入页面的方式,这里将ajax的结果放置到comments的后面
2、实现:
首先要在View中添加下面两个脚本文件:
<script src="http://www.cnblogs.com/Scripts/MicrosoftAjax.js" type="text/javascript"></script> <script src="http://www.cnblogs.com/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
定义表单:
<h4>Comments</h4> <ul id="comments"> </ul> <% using (Ajax.BeginForm("AddComment", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "comments", InsertionMode = InsertionMode.InsertAfter })) { %> <%= Html.TextArea("Comment", new{rows=5, cols=50}) %> <button type="submit">Add Comment</button> <% } %>这样就行了,我们发现比用Jquery方便很多,但是使用Jquery将灵活很多。
3、效果:和第二种一样。
总结:本文非常的简单,在asp.net mvc中实现了3中ajax的调用方式。推荐使用Jquery和Ajax Helper这两种。Ajax Helper使用非常简单,Jquery比较灵活。
参考:
ASP.NET MVC 2 In Action
Pro ASP.NET MVC 2 Framework, Second Edition
最新新闻:
· 微软不为外界所知的十件趣事(2010-07-18 22:58)
· 中国第2季搜索引擎市场规模达26亿 百度破70%(2010-07-18 22:54)
· Facebook用户数下周达5亿 邀请用户共享故事(2010-07-18 22:49)
· 开源的可视化编辑器 KindEditor 3.5.1 发布(2010-07-18 22:35)
· WordPress 陷入开源‘边界’之争(2010-07-18 17:47)
编辑推荐:揭秘Facebook背后的那些软件

作者: 陈希章 发表于 2010-07-18 18:29 原文链接 阅读: 481 评论: 6
引子
之前我写过一篇文章,讨论了在XML Web Service或者WCF中,多次发起异步调用可能导致的问题,请参考http://www.cnblogs.com/chenxizhang/archive/2010/05/31/1747812.html
在这一片文章中,我介绍了问题的症状以及发生的原因,及其解决方法。这篇文章收到了一些反馈,其中有朋友介绍到了Hprose这个产品。我后来也实际用了一下,确实在Hprose中是可以避免这种问题的。(有兴趣的朋友,可以参考这里 http://www.cnblogs.com/chenxizhang/archive/2010/05/31/1747812.html#1873774)
本着实践和求真的精神,我也专门对Hprose这个产品也做了一些深入的探究,包括和他们的开发团队做了一些交流。同时,因为这个产品是商业开源(与一般的开源还不太一样),所以也引发了一些对技术和开源的思考。今天整理出来,给大家参考参考
什么是Hprose?
Hprose (High Performance Remote Object Service Engine) 是一个商业开源的新型轻量级跨语言跨平台的面向对象的高性能远程动态通讯中间件。它支持众多语言,例如 C++, .NET, Java, Delphi, Objective-C, ActionScript, JavaScript, ASP, PHP, Python, Ruby, Perl 等语言,通过 Hprose 可以在这些语言之间实现方便且高效的互通。
Hprose 是商业开源软件,在取得 Hprose 商业使用授权后,您可以将它用于您所拥有所有权的商业项目的开发当中,Hprose 商业使用授权没有开发者人数、服务器CPU数量、授权年限等限制,但对二次分发有一定的特别要求。如果您所开发的项目或产品涉及到对 Hprose 的二次分发,还需要取得相应的二次分发授权。
关于Hprose的详细介绍和有关资源,请访问其官方网站: http://www.hprose.com
问答Hprose
下面记录了我和他们的团队几次邮件交流讨论到的几个一些问题。取自邮件的原文,比较直白,但是原汁原味。
问:协议层面,我关心的是主要包括两个层面:Hprose如何支持不同的传输协议(例如Http和Tcp或者还有更多的),以及Hprose的数据序列化格式是否有公开的规范书?
答:协议实现方面我们是这样考虑的,通过uri来区分不同的协议,目前http://、https://开头的是表示Http客户端和Https客户端,他们由HproseClient的子类HproseHttpClient来具体实现。当以后提供tcp、udp等实现后,tcp://、udp://开头的表示TCP客户端和UDP客户端,他们可能会分别由HproseClient的子类HproseTcpClient和HproseUdpClient来分别实现,每个不同类型的客户端肯定会有他们特有的属性,并且内部通讯机制也完全不同,所以由不同的子类实现是必要的,但是它们又都是HproseClient的子类,在不需要设置特殊属性的情况下,可以使用HproseClient来统一访问,另外,当tcp、udp版本实现之后,我们会给HproseClient类提供一个工厂方法,通过不同协议的uri来创建不同类型的HproseClient对象不需要指定使用哪个子类,这样就可以将不同协议的实现进行统一管理了。
【我的评论】这个做法也是可以的,采用类似于.NET中WebRequest那种工厂方法模式的设计,也能保证一定的灵活性。虽然与WCF那样通过配置文件直接就可以改变传输协议(其实是所谓的binding)的做法是有些差别的。
而数据序列化协议部分,目前我们没有公开的数据格式描述文档,这部分我们以后可能会通过标准或者专利的形式进行发布。格式的公开不是一个简单的问题,它有多方面的因素所制约,AMF这个格式从最初制定实施到最后公开也是花了5-6年的时间(2002-2006年制定,2007年公开发布),对于Adobe那样的大厂商尚且如此,对于我们而言也需要慎之又慎啊。
【我的评论】可以理解
问:数据传输层面,有没有办法由用户决定是否进行加密或者压缩?
答:可以由用户来决定加密和压缩。目前压缩是通过直接使用http的压缩方式,服务器端有个IsCompressionEnabled开关,当打开这个开关后,客户端只需要添加Accept-Encoding: gzip,deflate这个http头,就可以开始压缩传输了。不过说实话,压缩开启之后,数据量不够大时,数据压缩之后反而会增大,而且数据压缩传输会对CPU消耗相当严重,所以我们是不推荐使用压缩传输的,因此文档中并没有提到IsCompressionEnabled开关,也没有说明客户端如何开启压缩传输的方法,这样可以避免用户在误用这个功能后抱怨占用太多CPU。至于用户自定义加密传输,我们现在还没有提供这个功能,一是因为https本身可以提供加密传输,在tcp上也可以通过tcp+ssl实现加密传输。因为ssl是标准的,所以要比用户自定义的方式可靠一些。另一个原因是,加密传输要保证安全性需要用到密钥交换技术,这个同样占用大量的CPU计算时间,我们在Hprose的前身PHPRPC中提供了这个功能,但是我们发现它带来的这个缺点远远大于它所带来的问题(例如黑客可以通过这一点很轻松的发起DoS攻击,导致服务器计算资源耗尽而停止正常服务)。另外,密钥交换本身必须是一个同步调用的过程,在实现远程异步调用时,又要保证同步,会大大增加实现的复杂度,以及降低异步调用的效率。所以对于自定义加密方式传输的功能,我们目前的1.x版本中还不打算加入。当上面所说的几个问题能够找到有效的解决方法之后,我们会在Hprose 2.0或者Hprose 3.0中,以插件的方式来提供。
【我的评语】我们乐见这个设计的完善
问:是否有考虑过REST方面的支持?
答:REST相对于RPC是另外一种构架模式,Hprose提供了一种序列化机制,同时在这种序列化机制上构建了一个RPC机制。所以如果在Hprose的序列化机制上使用REST方式来构建系统也是完全可以的,但是这时候就完全不需要Hprose提供的客户端和服务器了,只需要Hprose的IO(序列化反序列化)部分就可以了。但是REST构架最大的问题是,它没有一个统一的标准,不能向RPC那样可以保证接口的互通性。而且应用的范围我认为也不应存在太大的交集,现在很多采用REST方式来提供类似Web服务功能的用法,大多都是对REST的误用,并没有发挥出REST本该发挥的优势。现在的REST已经像当年的XML一样被当成了万能灵药,而实际上,这已经背离了REST的本意。而Hprose既然是为RPC在XML火爆的年代中所犯下的错误做出的纠正,就不应该在REST火爆的年代犯下同样的错误。所以即使Hprose的序列化机制确实可以用于真正的REST应用,我们也不会明确的告诉大家Hprose可以做REST服务,因为在大多数人并不能真正认识REST的年代,这样说就是对用户的误导。
【我的评语】基本同意。对于REST,还是可以多从实践的角度去辩证地看待。
问:OnError事件的做法存疑,如果一个client发起了多次请求(方法名也是一样的),那么怎么区分呢
答:OnError事件确实存在您说的问题,这个问题我们在JavaScript、ActionScript、ASP这些版本中已经提供了在调用中直接提供跟调用绑定的错误处理回调的方式来解决了。但是C#、Java等这些版本我们在1.2版本中尚未提供这种解决方案(未提供的主要原因是用户对这个功能没有强烈需求)。但这个解决方案我们会在1.3版本中在所有语言中统一的。
【我的评论】这个机制还是需要完善起来,现在有用户对这个功能有强烈要求了
问:身份验证方面,我看到目前文档的说明是可以直接改写Http的头,添加Authencation这个标头。
- 我要说的是,这个部分最好有改进。目前这种做法易用性不高,会让人生畏。ADO.NET Data Service早先就遇到这个问题,后来改进了
- 身份验证和授权历来都是很重要的。身份验证本来就有标准的做法,例如给Client类型添加一个Credentials这个属性。而授权应该可以结合自定义Attribute或者给予Url的做法可能是较为合适的
- 后续这个方面最好有一些例子
答:对于.NET版本,我们确实提供了如您所说的Credentials属性,这个属性我们没有在手册中列出(因为他在其它语言中不存在,另外,.NET的某些版本中也不支持这个属性,例如SilverLight,这跟.NET本身有关),但是在使用时您会发现他确实存在。在服务器端授权方面,我们提供了 OnBeforeInvoke 事件,在该事件中可以对认证授权进行统一处理。我们不使用 Attribute 的原因是,我们认为 Attribute 不是一种松散耦合的解决方案,它对所发布的服务具有侵入性,我们设计的目标是,任何可以直接用于本地的方法都可以直接发布为远程方法,而不需要对它做任何修改或修饰。这样才可以保证,对于我们不具有源码的类也可以无需包装就作为远程服务发布,并且还可以对授权做集中控制。
【我的评语】这个设计我认为还是要改进,让用户使用起来更加方便一些
问:开发工具和服务描述方面的支持
- 这个部分最好有改进。例如我看到,如果直接在浏览器中输入服务的地址,会看到几个字符。那不是一个友好的设计。你可能主要是从开发者角度看这个问题了,而不是用户角度。
- 其实这一点可以借鉴WCF或者Web Service的wsdl做法,人家好的东西也可以吸收的
答:WSDL存在的意义在于它是上一代静态远程调用机制所必需的中间语言,就如同CORBA的IDL、ICE的Slice一样。与IDL和Slice不同的是,在.NET中,WSDL是根据服务自动生成的(但是对于PHP、Python这些非.NET上运行的语言,它们无法自动生成WSDL,需要手工编写,所以在PHP、Python等动态语言中发布WebService是相当痛苦的一件事情)。而Hprose是新一代的动态远程调用,所以不需要WSDL这样的中间语言。通过浏览器来查看Hprose的服务地址显示的远程方法列表虽然对用户来说不够友好,但是相比WSDL来说,Hprose的输出还是简单易懂的多。所以,我想您所说的WCF和WebService提供的用户友好的界面应该是指的在线调试界面,而不是WSDL那个页面吧。针对这个用户调试界面,我们提供了忘忧草(在线试用版地址:http://www.hprose.com/nepenthes/)这样的专业调试工具,用户如果需要调试服务,可以直接在这个调试工具中输入服务器地址,这样不管用户的服务是使用何种语言在何种平台上发布的,都可以采用同样的方式进行调试。而且随着这个调试工具的升级,用户以后可以用更加友好的界面来调试之前的服务,而不需要连同服务一起更新后才能使用新的调试界面。这都是我们为什么要采用这种分离式调试工具的原因。而您所说的WCF和WebService服务发布后的调试界面是.NET中特有的,如果用其它语言发布WebService服务,并不会得到这样的调试界面,所以,不同语言下的WebService服务,用户体验会有相当大的差别,而且用.NET老版本发布的WebService服务也不可能使用新版本.NET发布WCF服务的调试界面来调试,当然这并不是微软的错,而恰恰这是微软的策略,因为只有这样才能将用户牢牢的绑定于.NET平台之上,并且让用户始终追求使用最新版本的.NET平台开发工具,只有这样才能保证微软持续盈利。而我们的出发点恰恰相反,我们是要为所有平台所有语言的用户提供统一的用户体验,所以我们采用了截然不同的设计方式。
【我的评语】提供类似于WSDL这样的服务描述(甚至有配套生成客户端那个接口的工具)肯定是对的做法,让用户使用起来更加方便才是目标。统一的用户体验固然是没错的,但统一的用户体验不是说统一的不高的用户体验。
问:如果服务器端有两个类,他们拥有同名方法,则它们是无法区分的。看起来是以最后注册的类为准。这个有没有什么可能的问题。也就是说,在Client端Invoke的时候,只是提供了functionName,而没有办法提供服务类的名称。
答:你说的这个问题,我们一开始就已经考虑到了。所以我们提供了一个别名机制,如果以类(或对象)为单位发布服务,则可以为每个类(或对象)指定一个服务名成空间(该名称空间在发布服务时会变为方法前缀),而对于以方法为单位发布服务时,则可以为每一个方法指定一个完整的别名,通过完整的别名,就可以区分在定义时名称相同的两个不同方法了。这部分在文档的后面部分(客户端部分)有比较详细的说明。
例如您的这个例子可以这样改写:
class Program
{
static void Main(string[] args)
{
HproseHttpListenerServer svr = new HproseHttpListenerServer("http://localhost:2010/Hprose/");
svr.Methods.AddInstanceMethods(new MyService(), "s1");
svr.Methods.AddInstanceMethods(new MyService2(), "s2");
svr.Start();
Console.WriteLine("服务器已经准备就绪");
Console.Read();
}
}
【我的评语】这是不错的
问:对于开源的理解
答:我对开源的认识,大概开始于10年之前第一次接触Linux吧。那时的Linux发展了已有10年之久,因为其开源,功能又不逊于Unix,因此许多公司都希望藉由Linux操作系统,来取代昂贵的Unix,以便在激烈的竞争中取得有利的地位,这方面的代表是RedHat、SuSE等商业化 Linux 版本。而另外一些个人或组织则为了教育科研的需要而开发了适合自己的Linux版本,这方面的代表是Slackware。还有一部分个人和组织则是为了兴趣和自由的理想而开发他们自己的Linux版本,这方面的代表是Debian、Gentoo等。虽然大家做的都是Linux,但是出发点不同,因此各个产品之间当然会出现很多的差异化,以致于想要开发一个可以在所有版本Linux都能运行的程序都是一件很困难的事情。Linux阵营因此而分裂,形成了诸侯割据的局面。各诸侯之间的争斗一直在继续,一批死去,一批新的又起来,何时才能统一,不得而知。
而Windows自始至今都是不开源的,也正是因为这样,Windows才保持了统一的局面,而没有像Linux那样四分五裂。尽管Linux阵营常常以Windows不开源为借口来打击Windows,但是Windows的霸主地位始终没有丝毫的动摇,相反因为Linux阵营的四分五裂,各个厂商之间各怀鬼胎,虽然势众,但并不能团结一致,甚至一些公司为了自己的私利,还跟微软签署了合作协议,例如Novell(SuSE和Mono的开发公司)。这就像苏洵在六国论中指出的“六国破灭,非兵不利,战不善,弊在赂秦”一样,Linux照这样发展下去最终必会败于Windows系统。
Linux的开源始于对自由理想的追求,但好的理想却常常会被恶的思想所利用,以致善始而不能善终。
我理解的开源是这样的:
OpenSource != Free != No Charge
开源的目的一般分为以下几种:
1、以自由作为理想的开源。代表为GPL开源许可。GPL的发起人铁人(他名字的直译)是一个理想主义者,他认为软件是自由的,一个软件被开发出来之后,人人都可以修改它,人人都可以维护它,任何人都不可以剥夺别人修改软件的自由。但是他的这个理想常常被人误认为软件必须是要免费的。也就是被误认为 Free == No Charge,但实际上,铁人并没有这个意思,而且他自己也确实在通过他的自由软件所盈利。
2、以打击竞争对手或者潜在的竞争对手为目的并把开源贡献者作为免费劳动力的开源,代表为Apache基金会、Mozilla基金会。Apache基金会幕后最大的支持者是IBM,IBM通过赞助Apache基金会来开发一些免费的开源项目,这些开源项目最大的特点是商业友好,也就是说,可以免费的拿来商用且不用继续开源,Apache的开源项目作为一个试验田,由众多小公司拿来免费使用,在使用过程中遇到问题并不能得到任何的商业支持,只能通过自己努力来解决,解决之后在反馈给Apache组织(当然也有大部分人并不会提交自己的努力成果)。而IBM则会拿Apache的那些半成品来经过自己的优化之后,做成高端产品,再以高价卖给高端客户。这样,低端客户有免费的Apache开源项目使用,虽然难用但因为不用花钱,所以就不会选择收费的其它低端市场定位的同类商业产品,尽管那些商业产品可能要比Apache的开源项目优秀的多。而高端用户有因为不在乎花钱,所以只买最贵的,因此IBM的产品就成了他们的首选。IBM通过这种方式有效的打击了低端市场的同类产品,使他们无法成长为可以跟IBM叫板的竞争对手。而Mozilla基金会可以说是一个复仇组织,当它的前身Netscape被微软的IE消灭之后,Mozilla就把打败微软的IE作为了首要目标,因此Mozilla的开源免费完全是为了解决掉微软的IE。不过螳螂捕蝉,黄雀在后,Mozilla经过这么多年的发展,虽然终于可以争取到一点IE的市场份额了,没想到Google的Chrome也进入了浏览器竞争市场,面对这两大高手,Mozilla要翻身恐怕是很难了。
3、为了让客户放心使用而开源。代表是微软和Hprose。微软现在有很多产品会对某些要求查看源码的客户开源,比如某些国家的政府,这种开源仅仅是为了让客户放心使用,证明自己没有留下什么后门。Hprose的开源也是类似的想法,对客户开源,让客户放心使用,当然如果客户遇到问题,因为手中有源码,也可以更容易的反馈错误,我们就可以更快的完成错误修正。所以,这种开源方式是一种双赢的做法。
4、盲目开源。代表是Sun。他在IBM的怂恿下,把Java开源了,最后IBM搞出了自己的JVM,赚翻了。而Sun自己一分钱没赚到,最后把自己公司都搭了进去,以致于最后落了个被Oracle收购的下场。
【我的评语】对于开源向来大家理解都不一,上述总结比较中肯。我个人也赞同:开源不等于免费
问:那个PHPRPC开源,你怎么评价?
PHPRPC 现在是以GPL形式开源的,也就是说,它也是一个理想主义的产物,任何人都可以得到它,修改它,使用它,却不能独自拥有它,不能将它私有化。实际上PHPRPC也是我们的一个产品,但是它只能用于同样采用GPL发布的项目中,我们对它也提供收费的商业支持,但实际上,你知道的,我们根本不可能在这方面得到一分钱的收入,因为在国内,只有理想是不能养活一个公司的,甚至连个人都不能养活。呵呵。但是既然已经做了,就让它继续下去吧,只要它还活着,就代表我们还有理想,我们还在奋斗!
【我的评语】为理想和奋斗者而鼓掌
最后,我还是要表达我对Hprose的整体评价:
-
我对Hprose的构想和设计比较赞许,跨平台跨语言支持当然是很多程序员乃至CTO们孜孜以求的目标。而Hprose在实践这样的目标,这最起码是值得我们学习并且为之欢欣鼓舞的。希望这个产品能精益求精,做得更好,并且能得到更多人的了解和使用。
-
对于Hprose团队的创造性工作和认真态度,我是颇感欣赏的。希望他们能坚持理想,实现理想。对于开源,经常有人感概说,看似很好,但实践起来却殊为不易,我自己也深以为然。从这方面而言,更应该赢得我们的敬意和支持。
最新新闻:
· 微软不为外界所知的十件趣事(2010-07-18 22:58)
· 中国第2季搜索引擎市场规模达26亿 百度破70%(2010-07-18 22:54)
· Facebook用户数下周达5亿 邀请用户共享故事(2010-07-18 22:49)
· 开源的可视化编辑器 KindEditor 3.5.1 发布(2010-07-18 22:35)
· WordPress 陷入开源‘边界’之争(2010-07-18 17:47)
编辑推荐:揭秘Facebook背后的那些软件

作者: 倪大虾 发表于 2010-07-18 18:10 原文链接 阅读: 725 评论: 20
今天吃小龙虾的时候忽然想到了以前一个湖北朋友讲的虾的故事.这位朋友是湖北人,据他说在他小时候他们那里很多虾,特别是夏天雨后,满地爬的都是.因为传说那是美国对付中国的秘密武器,居然没有人敢吃.后来偶然有人提了半桶换卖了5块钱回来,慢慢的大家认识到虾的价值,随后就有了今天吃得五香小龙虾.然而近几年出现的"洗虾粉"又让人心有余悸.回想起昨天看到亚力山大<召集讨论设计模式是语言表达能力低下的产物>一贴.突然发现设计模式和虾居然有相似的命运.
设计模式从出现到发展,到普及再到今天,人们对它的认识也同样经过了"陌生"->"认识使用"->"批评".设计模式在程序员心目的地位中也经历了"新奇"->"圣经"->"怀疑".然而,不管人们如何认识龙虾,从始至终虾还是虾,没有变过.同样,设计模式自出现现到今天,一样没有变,变得只是次第更新的软件设计开发技术,变得只是一代又一代的程序员.
设计模式是20世纪60-70年代的软件危机之后大规模软件的发展的结果.这里有个问题,什么是设计模式.相比能够真正回答正确的人不多,真正理解的人也不多,因此经历的辉煌之后随之而来的怀疑就不可避免了,不过也正是这些批判怀疑促进了设计模式更进一的发展.
什么是设计模式,我也无法给出权威的答案,不过我敢肯定,设计模式不是<gof23种设计模式>中的UML图,也不是一行行的示例代码,它有的只是一种思想,一种思考问题的方式,就像<加勒比海盗>中的<海盗法典>,它只是指导,而并非律法.
既然只是一种指导,那么在使用的时候就应当根据实际情况使用它或不使用它,用一种方法实现它或用另外一种方法实现它.指导告诉我们一个解决问题的方向,而例子告诉我们到达目的地众多路径中的一条,它可能是最优,也可能是最差.<gof23种设计模式>一书不仅详细的表达了什么是设计模式,而且有很多生动的例子.这些例子用来具体说明每种设计模式.然而在今天看来,那些Smalltalk或C++的例子却成了一幅无形的枷锁,让很多人去套用而不知道因地制宜的发散扩展.比如当不断的用if ...else if选择工厂或策略的时候,就不会想到在.NET中可以使用反射来去掉让人生厌的if...else.
今天讨论的是.NET中的设计模式.大家都知道设计模式出现时还没有.NET,Gof不可能预见会有C#的出现,写论文的时候也不可能知道有反射,委托,事件等技术的出现.因而亚历山大同志单凭"比如C#内置了事件机制,那么Observer还有意思"就认为设计模式已过时就显得过于武断了.
.NET中有很多特性使得设计模式的实现更加简单,然而并不是说一定要用这些特性来实现设计模式,,就好比有了乘法,有时候我们用加法实现1+1=2可能更好,你不能因此而否定了乘法.同样,既然"事件"能够实现"Observer"的效果,那么一个事件不正是一个Observer吗?Observer不是加入到.NET中了吗!它只不过换了个名字,本质没有变.
所以说我们在用设计模式的时候首先应该深入挖掘语言的潜力,而后结合设计模式的思想,创造独有的应用设计模式.或许在C++中实现一个Observer有很多行代码,在.NET中一行即可.书中的例子只是学习的一种途径,没有创新,生搬硬套只能是鹦鹉学舌,邯郸学步,最终也只是贻笑大方了.
最新新闻:
· 微软不为外界所知的十件趣事(2010-07-18 22:58)
· 中国第2季搜索引擎市场规模达26亿 百度破70%(2010-07-18 22:54)
· Facebook用户数下周达5亿 邀请用户共享故事(2010-07-18 22:49)
· 开源的可视化编辑器 KindEditor 3.5.1 发布(2010-07-18 22:35)
· WordPress 陷入开源‘边界’之争(2010-07-18 17:47)
编辑推荐:揭秘Facebook背后的那些软件

作者: CoolCode 发表于 2010-07-18 17:46 原文链接 阅读: 778 评论: 13
传说中的dynamic
dynamic是个不合群、不按规则办事的家伙,可以说是个异形,但更恐怖的是它又是无所不知的,任何事情都难不了它(咳咳,它似乎与Lambda表达式是死对头)。这令人想起《死亡日记》的怪异侦探L,行为怪异而智力超人,以至于离奇的案件不得不交给了他。dynamic可以看成是一切类型的化身,但并不是仅限于此,它像《未来战士》续集里面的T-1000型液体金属的终结者。噢~~~~似乎扯的有点远了
饱经风雨而不倒的ADO.NET
ADO.NET 从来做事都有理有据,而且又异常专注于自身领域,是个professional的牛人,令人想起《美丽心灵》里面的博弈论和微分几何学领域潜心研究以致获得诺贝尔经济学奖的数学家—— 约翰·福布斯·纳什 教授(咳咳,纳什教授是个妄想型精神分裂的~~~嗯,这个以后再说)。
关于ADO.NET 的例子
1. 执行SQL语句
using (DbCommand command = connection.CreateCommand()) { command.CommandText = "select Top 10 * from Orders"; command.CommandType = CommandType.Text; using (IDataReader reader = command.ExecuteReader()) { while (reader.Read()) { Console.WriteLine("OrderID: {0}, OrderDate: {1}", reader.GetInt32(reader.GetOrdinal("OrderID")), reader.GetDateTime(reader.GetOrdinal("OrderDate"))); } } }
2. 调用存储过程
command.CommandText = "CustOrdersOrders"; command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(new SqlParameter("CustomerID", "ALFKI")); //略去...
当 ADO.NET 遇上 dynamic
某年某月ADO.NET不幸遇到dynamic,从此循规蹈矩的生活不复存在。dynamic说它可以帮助 ADO.NET 丢掉 DataSet 的包袱,而且在不用创建数据实体的情况下,实现查询结果垮不同方法传递;更加强大的地方是可以与存储过程无缝连接,即像调用一般方法一样调用存储过程而不用写额外代码。我的神哪~~~ ADO.NET 听了dynamic一番游说后,心底下不禁惊讶一下。dynamic又说,实现刚才所说的工程只要借你手下的两大猛将 SqlConnection 和 SqlCommand 助我一臂之力即可。
dynamic真有如此奇技? ADO.NET 虽有怀疑,但它想到曾经看过一部叫《阿甘正传》的电影,里面的阿甘虽然是弱智人,但参军时练就乒乓奇技,后来还和中国国手同台竞技。想到这,ADO.NET 认为不能因为对方弱智就不相信对方的话,这是很不礼貌很不绅士的人才会做的事,所以它相信了dynamic。
dynamic 果真不负众望,三两脚猫功夫就交出成果了。
dynamic重构后的数据库操作
using (dynamic command = connection.CreateDynamicCommand()) { //执行查询SQL IEnumerable<dynamic> toptenOrders = command("select Top 10 * from Orders"); foreach (dynamic order in toptenOrders) { Console.WriteLine("OrderID: {0}, OrderDate: {1}", order.OrderID, order.OrderDate); } //执行带参数的SQL IEnumerable<dynamic> customerOrders = command("select * from Orders where CustomerID = @CustomerID", CustomerID: "ALFKI"); foreach (dynamic order in customerOrders) { Console.WriteLine("OrderID: {0}, OrderDate: {1}", order.OrderID, order.OrderDate); } //调用存储过程 IEnumerable<dynamic> orders = command.CustOrdersOrders(CustomerID: "ALFKI"); foreach (dynamic order in orders) { Console.WriteLine("OrderID: {0}, OrderDate: {1}", order.OrderID, order.OrderDate); } }
要知道 ADO.NET 可不是.NET菜鸟,它看到 command("select Top 10 * from Orders"); 第一感觉认为吃了dynamic药的command有可能是委托类型,而看到后面的 command.CustOrdersOrders(CustomerID: "ALFKI"); 不得不否决了前面的看法。dynamic到底是什么东西?可以这样认为,dynamic什么东西都是;也可以认为,dynamic不是什么东西!
ADO.NET 知道任何.NET写的再高深的代码在reflector下都会现出原形,通过对 command 解剖,立刻明白原来自己跟《美丽心灵》的纳什教授一样纠缠于一种不存在的幻想不能自拔,reflector告诉我们:dynamic实际上是不存在的!
还是鲁迅叔叔说的好,世界上本没有dynamic,只是微软对委托封装得太牛了,也便有了dynamic。
结语
聪明的你知道command是怎么实现了吗?不妨先想想,然后展开下面的代码看看是否与你想的一致。
注:本文存储过程部分参考了微型ORM.
最新新闻:
· 微软不为外界所知的十件趣事(2010-07-18 22:58)
· 中国第2季搜索引擎市场规模达26亿 百度破70%(2010-07-18 22:54)
· Facebook用户数下周达5亿 邀请用户共享故事(2010-07-18 22:49)
· 开源的可视化编辑器 KindEditor 3.5.1 发布(2010-07-18 22:35)
· WordPress 陷入开源‘边界’之争(2010-07-18 17:47)
编辑推荐:揭秘Facebook背后的那些软件