|
|
2006年9月28日
http://blog.robinzhong.com/index.php/archives/2006/09/28/125.html 刚开始用Live Writer就开始找这样的插件. 终于,找到很多.不过ms大多数人都是用的这个插件: Syntax Highlighter for Windows Live Writer . 当然,我也用了这个插件... 总的来说,基本功能满足了,不过,它只能格式化代码,然后对其中的一些关键字高亮.除此之外,ms木有什么别的新的功能了(比如代码块隐藏,Line Number) :( 以前在博客园的时候,很习惯于使用 Actipro CodeHighlighter ASP.NET 这个代码高亮插件.但是现在网上还没有人基于这个免费的工具写一个Live Writer的插件出来.真是遗憾啊...
摘要: http://blog.robinzhong.com/index.php/archives/2006/09/28/124.html 在M$平台上面开发软件,很有可能要和COM+组件交互.或者写一个COM+组件,或者调用这样的一个组件. 但是M$只提供了MMC来管理COM+组件,没有提供的命令行的版本来增加/删除/修改COM+组件 ( 这是M$的一个习惯.不知道 PowerShell出来后会不会好一... 阅读全文
2006年8月23日
摘要: WebService Interface? 什么东西? 为什么要这个玩意儿,它有什么用?
有这样一种情况: 我有一个Client程序,要引用到多个Web Service,这一些Web Service的调用方式是一样的,只是各自Web Service本身的实现有一些区别.那么,对于Client来说,最好的调用方式就是这样的:
......
即通常说到的基于Interface的编程...
但是Web Service的实现和普通的Interface又有一些不同.下面是一个例子,记录了如何使用Web Service Interface. 阅读全文
2006年6月9日
From: http://blog.robinzhong.com/index.php/archives/2006/06/09/112.html
idior 前两天在cnblogs发表了一个关于O/RM的文章 “O/R Mapping乱弹”.
呵呵,他来乱弹,我也来弹弹.
对于O/RM还是R/OM.正如你在文中提到的,O/R M这个概念是从Java社区传过来的. 在这之前, M$这一块是没有这样的事物可以对应的.
因为Java正火的时候,M$还在推行当时的Windows DNA架构.Windows DNA的架构就是一个C/S式的架构,使用COM/COM+等来完成远程通讯. 但是后来因为基于Internet的B/S结构的流行,使得Windows DNA推行的并不是太成功.
M$看着Java在企业的应用很流行,于是开始偷偷的学,也想进入企业级的开发领域,于是就有了.NET ( 当然,这个只是偶的猜测.也有人说,Win32API到现在已经很好了,不过缺陷却是Procedure试的开发,不是当时正在流行的OO式的开发.于是 ,对这一些低层的Win32 API进行了OO式的封装,于是有了.NET fx.后来追求完美的人发现C++太复杂了,于是便发明了新的C#)
但是当时M$在企业的开发领域还不是太了解,没办法挤进去.所以只好以曲线救国的方式. 从农村包围城市,先让开发者都学会.NET,从小的项目做起. 为了给大家提供一个.NET下面开发的参考,M$使用是最直接,最容易明白的方式 — 以数据库为中心.
以数据库为中心,指是的设计的原则. 在Design开始前, 根据Requirement来定义数据结构,然后把数据结构反映到数据库中去.通过数据在db中的关系(PK/FK之类的)来决定对应在程序中对象的关系. 即程序中的对象都是数据库结构的对应,然后再使用Transaction Script的方式来调用. 这带来的好处就是简单,容易.不用太多的考虑OO的概念,也不会有太多复杂的Logic (因为是小的系统嘛.) 坏处也是不言而喻的.没有Practise太多OO式的开发,对于复杂的Logic就显得心有余而力不足了.
在Java中,数据库只是用来存储数据的.但是现在主流的db还是结构化的,不是面向对象的DB.所以于对java程序员而言,过多的考虑数据的存储结构以及数据的读写,是一件很恼火的事. Java程序员说,我要有一个解脱的工具,于是,便有了O/RM. 解放出来的程序员们,可以更加Focus在对象模型的建立上面了,更加专注Design Pattern方面的建设了.
现在, .NET把 O/R M 也引入了.但是因为一开始的设计模型就不是一样的,所以不是太习惯于 O/RM的使用,在某些用法上面是和Java中的 O/RM是”背道而驰”的,并不符合M$给大家带来的思维方式. 基于这种理由/假设,M$取消了曾经Plan中的 ObjectSpace, 转而向 DLinQ了.继续M$在.NET开发中的领导位置
2005年12月24日
前一段时间,打个机会买了一个空间.于是自己做了一个blog系统.
于是把所有的数据导入到自己的空间中去了~
以后的主力blog就是自己的blog站点了: http://www.robinzhong.com/
博客园的blog也会更新的,不过应该还是只限于.NET相关了的:)
欢迎大家来我的新blog参观:)
2005年5月27日
摘要: 昨天发了,Infopath Cookies(1) .今天再发:)这个文章主要写的是关于Dropdownlist的数据绑定...1,最简单的方法,从控件上拖一个DropDownList到界面上面,在其属性选择"手动输入列表框项",然后自己把其中的数据一个个的填写到下面的表格中...上面的方法应该是用的最多的了吧..方便,想写什么就写什么.爽..不过缺点就是静态的,不能动态进行修改.使用上有限制:(2... 阅读全文
2005年5月26日
前一段时间做Office开发,用到了Biztalk和Infopath... 如前文( 在Biztalk中使用Log功能:) ) 所提到的,Biztalk直是太强大了... 而且,后面和别人的聊天中得知,Biztalk的强大在于他可以很方便的把各种异构的环境进行统一,整合. 这对于企业的开发特别重要...谁都不想自己以前的投资一下就没了(打水漂了,完全重来)... 只是可惜,Biztalk的版本才是2004,即刚刚出来只有一年的时间,按M$的习惯,相关的文档是少之又少.....学习的难度比较高... 在使用Biztalk开发的时候,一般情况下面,它是直接可以把Hws等服务发布成WebService.那么调用就直接可以通过ASP.NET或是WinForm调用Web Service使用了... 不过,M$在Office2003中加入了一个新的产品-Infopath. 想必很多人都知道这个东西的...(但是,真正用过的,又有多少呢?.呵呵) Infopath的表单,本质上就是一个XML文档,使用特定的XSLT进行显示,通过JScript进行交互...通过Infopath内置的功能,可以很轻松的实现WebService的调用(这个是Infopath最大的优点之一).同时,由于这个特性,Infopath在一些场合下面完全可以代替ASP.NET页面. Infopath开发方便,直接调用WS,不用像ASP.NET一样写过多的代码.直接的结果就是开发成本降低(你不用去理会什么ViewState之类了的),同时也能减少开发周期(直接拖控件,直接就可以和数据源进行绑定)... 现在说几个Infopath开发的Cookie: 1.手动调用设计时加入的WebService. 在使用Infopath设计器时,我们是可以直接加入WebService的引用的(通过 工具->辅助数据源 进行添加),在添加后,我们可以选中文档打开时调用...但是,一般情况下面,我们大都不会把所有的WebService在文档打开的时间进行调用的.所以我们需要一种在其它的时候调用WebService的方法: 对于每加入的一个数据源,都会在 XDocument.DataObjects 中增加一个Object.通过此Object的Query()函数,我们就可以手动调用WebService了. 比如调用GetTaskInfo 这个WebService:
XDocument.DataObjects.Item('GetTaskInfo').Query() 当然了,我们可能得给这个WebService传参数,或得到其返回值.. 为了操作,我们先加入WebService的引用(如上面的GetTaskInfo),然后提取表单文件.提取后的文件里面,我们可以找到GetTaskInfo.xml GetTaskInfo1.xsd等文件.这里的GetTaskInfo.xml就是我们调用此WebService时传递的Soap的xml结构.打开这个文件,我们可以看到如下的结构:
<dfs:myFields xmlns:dfs="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution" xmlns:ns7="http://microsoft.com/Biztalk2004/Hws/Hwsservice"><dfs:queryFields><ns7:GetTaskInfo><ns7:taskID></ns7:taskID></ns7:GetTaskInfo></dfs:queryFields><dfs:dataFields><ns7:GetTaskInfoResponse><ns7:Task></ns7:Task></ns7:GetTaskInfoResponse></dfs:dataFields></dfs:myFields>
 其中,<dfs:queryFields/>中的<ns7:GetTaskInfo><ns7:taskID/></ns7:GetTaskInfo>就是此WebService的参数. <dfs:dataFields>中的就是返回值了. 即,我们只要在调用WebService前把这个文件中的<dfs:queryFields>填入参数,调用后从<dfs:dataFields>取回返回值就OK了... Come on. Let's go! 代码:
var oAuxDom = XDocument.GetDOM('GetTaskInfo');
oAuxDom.setProperty("SelectionNamespaces", 'xmlns:dfs="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution" xmlns:ns7="http://microsoft.com/Biztalk2004/Hws/Hwsservice');
oAuxDom.selectSingleNode("/dfs:myFields/dfs:queryFields/ns7:GetTaskInfo/ns7:taskID").text=taskID;
XDocument.DataObjects.Item('GetTaskInfo').Query();
var propertyNode;
var returnTask = oAuxDom.selectNodes("/dfs:myFields/dfs:dataFields/ns7:GetTaskInfoResponse/ns7:Task"); returnTask就是此WebService的返回值了...此WebService的调用就Over了~ 2.动态修改WebService的调用地址: 在Infopath设计的过程中,我们可以直接添加WebService的地址.非常方便.但是在布署的时候会有问题.因为布署时的WebService安装的机器是不确定的.如果WebService的地址每改一次就要重设计一次Infopath,那不是太麻烦了:( 这里,我们还是得用到XDocument.DataObjects这个对象了~ 同上面的,我们把提取表单文件.关闭Infopath,用Notepad打开mainifest.xsf文件. 我们可以在里面找到类似这样的代码:
<xsf:dataObjects>
<xsf:dataObject name="GetTaskInfo" schema="GetTaskInfo.xsd" initOnLoad="no">
<xsf:query>
<xsf:webServiceAdapter wsdlUrl="http://localhost/HwsService/HwsService.asmx?WSDL" queryAllowed="yes" submitAllowed="no">
<xsf:operation name="GetTaskInfo" soapAction="http://microsoft.com/Biztalk2004/Hws/Hwsservice/GetTaskInfo" serviceUrl="http://localhost/HwsService/HwsService.asmx">
<xsf:input source="GetTaskInfo.xml"></xsf:input>
</xsf:operation>
</xsf:webServiceAdapter>
</xsf:query>
</xsf:dataObject>
.
</xsf:dataObjects> 看到了没有,这就是一个DataObjects,里面有一个名叫GetTaskInfo的DataObject,是不是和上面的那个GetTaskInfo的DataObject很像?都有一个Query? 嗯.这个就是上面的那个XDocument.DataObjects.Item("GetTaskInfo")对象...既然这样,都是XMLNode.那么就有办法可以修改WebService的地址了:) 示例代码:
var wsObj = XDocument.DataObjects.Item('GetTaskInfo');
var url = "you new ws address.";
var objOperation = new ActiveXObject("MSXML.DOMdocument");
objOperation.async = false;
objOperation.validateOnParse = false;
objOperation.loadXML(wsObj.QueryAdapter.Operation);
objOperation.selectSingleNode("//xsf:operation/@serviceUrl").text = url;
object.QueryAdapter.Operation = objOperation.xml; 这样,我们只要在调用Query()函数前先调用这个语句,就可以动态修改WebService的地址了~ 呵呵,不要问我怎么得到那个Url啊...简单啊,在最前面放一个TextBox,让用户自己去填.或是直接使用JScript访问注册表,从注册表中得到Url(可以试试,我没试过). 大家一起来Infopath...
2005年4月13日
这几天,因为一些其它的原因,要使用BizTalk完成一个工作流的东西...刚看的时候,好晕啊.基本上完全不懂. 不过,幸好有M$的关于BizTalk的一些教学光盘.总算知道BizTalk是怎么一回事了:) 说实话,BizTalk真是一个好东西,可以很方便的把很复杂的工作流实现.而且实现的方式也相对比较简单,只要设计好xml Schema.在业务流程中把各种控件按你设想的流程拖进去.再设置一下,部署到BizTalk中去.就可以运行了:) 同时,BizTalk可以直接发布成WebService,为开发解决了很多的麻烦... 总之,BizTalk这个软件真是太强大了..一个字."爽". 在学习过程中,我是在虚拟机上跑BizTalk的.自己的机器的内存本来就不高,CPU也不强,跑起来真是好慢啊:( 开发的时候还比较好,不至于很慢.但是一旦部署完了,业务流程跑起来的时候发现错误了,想要进行调试就很麻烦了. (你想想,在虚拟机中,开着VS.NET 2003.,BizTalk,SQL Server,再通过BizTalk的 " 运行状况和活动跟踪" 来调试业务流程,那不惨不忍睹啊:( ) 幸好BizTalk提供了"表达式",可以调用.NET中的所有静态方法... 这下子,我们可以直接使用.NET中的FileStream,把流程经过的每一步都记录下来了(虽然比较麻烦,但是像我这种刚开发学习的人而言是比较方便了~) 如图:  1,建议一个新的dll工程.增加一个Log类,提供一个静态方法Write.用于把信息写入到一个文件.生成一个强签名文件,并加入到GAC中. 示例代码如下:
public class Log
 {
private static string m_file = @"C:\Temp\info.txt";
private static FileStream fs = new FileStream(m_file,FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.ReadWrite);

public static void Write(string Message)
 {
fs.Seek(0,SeekOrigin.End);
Message += "\r\n";
byte[] buffer = Encoding.ASCII.GetBytes(Message);
fs.Write(buffer,0,buffer.Length);
fs.Flush();
} 2.在Biztalk的有业务流程的项目中加入这个dll的引用. 在想要记录的地方加入一个"表达式"(如上图).在其属性->表达式中填入下面代码: Namespace.Log.Write(Message);
把Namespace换成上面Log类的实际的Namespace,Message就写你自己想写到文件中的信息. 3,编译,部署.测试:) 如果一切正常,那么你将会看到在预期的路径下面出现一个info.txt文件,里面记录着你的这个业务流程的真实运行路径. 通过这个比较简单的方法就可以很轻松的知道此业务流程那里有问题了~ 可以先不用使用 "运行状况和活动跟踪" 来查看了(免得系统太慢,等得受不了) 国外有一个老兄 Scott Colestock写了一个文章,关于在BizTalk中使用Log4Net来跟踪流程运行状况的. 有兴趣的可以看看这个文章: Diagnostic Tracing with BizTalk 2004 ps,这们老兄有一个项目,是使用Nant来Deploy Biztalk 2004的Solution :),感觉比较好玩~ 总结:其实这很简单的,就是使用了BizTalk 2004的.NET的支持,可以在"表达式" 中调用所有的.NET的静态方法... 汗啊,总是感觉没发些什么比较有技术含量的文章啊:(
2005年4月4日
在使用NUnit进行开发的时候,TestCase是不可省的.通过TestCase,我们才可以保证所撰写的代码的正确性:) 但是由于在开发过程中是边写TestCase,边实现功能代码的,如果不注意的话,在最终的Release版本中可能会出现曾经写过的TestCase...这应该是在程序开发过程中尽量避免的:) 解决这个问题的方法有以下几种: 1,使用 #if DEBUG XXX #endif 标签.将所有的TestCase放到此标签中.这样当以Debug方式编译的时候,可以使用NUNit进行测试.当以Release方式编译的时候,其中的所有代码将会被忽略掉(相当于注释掉).这样就不会产生多余的代码了:) 2,将所有的TestCase放到单独的工程中.这样,功能代码将不可能包括测试代码,这样也可以避免上述问题.. 在一个项目中,为了对所有的代码进行上述检查,如果用人工的方式来检查,那显然是不现实的.即然大家都是玩电脑的,那何不用电脑来检查了:)呵呵,对了,使用.NET下面的FxCop... FxCop自带的Rules里面没有这样的规则,那我们得自定义一个Rule了:) 此Rule的工作流程如下: 1,得到此程序中所有的Class. 2,对每一个Class,得到其Attribute. 3,对每一个Attribute,判断是不是NUnit.Framework.TestFixtureAttribute.如果是,返回错误. 注:一定要是Release版本的程序,才可以起到真正的检测目的. 通过 定制FxCop规则示例之一:AvoidICloneableImplementation 这篇文章,我们可以学会怎么编写一个基本的FxCop的Rule...但只是文章中的东西是不能解决我们的这个问题的..我们来Google一下,看看有没有别的信息.. 找到了这个: Writing custom rules [using introspection] for FxCop 1.312 (from: James Geurts) FxCop Custom Rule - Introspection Engine 3.12 注意这段:
The BaseIntrospectionRule class provides some overloaded versions of the Check( ) method. The available methods are:

Check(Member member)
- Useful for checking members of a class. (Methods, Properties, Events, Delegates, etc)
Check(Module module)
- Useful for checking assemblies.
Check(Parameter parameter)
- Checks all parameters
Check(Resource resource)
- Checks all resources (from .resx files)
Check(TypeNode type)
- Checks types
Check(string namespaceName, TypeNodeList types)
- Checks types 对于我们现在要编写的Rule而言,我们要使用第5个函数,即: Check(TypeNode type) 通过对TypeNode类的使用,我们可以发现他有 Attributes 这样一个属性,即可以获得此Class上的所有Attribute. 其类型是 AttributeList.. AttributeList中存放的是AttributeNode,不同于.NET FX中带的Attribute.即不能直接判断AttributeNode == Attribute. 幸好TypeNode提供了FullName属性.这个属性中存放的是实际类的全名. 即NUnit.Framework.TestFixtureAttribute类的TypeNode的FullName是 "NUnit.Framework.TestFixtureAttribute" 到这里,技术上的工作都搞定了..下面是代码实现 RuleInfo.xml
<?xml version="1.0" encoding="utf-8" ?>
<Rules FriendlyName="Avoid NUnit TestCase in Release Version">
<Rule TypeName="AvoidNUnitTestCase" Category="Cnblogs.Rules" CheckId="hbifts000001">
<Name>Avoid NUnit TestCases Implementation in Release Version</Name>
<Description>NUnit TestCases must never be included in release versions.</Description>
<Url>http://www.cnblogs.com/hbifts</Url>
<Resolution>Type '{0}' Implements NUnit TestCases, which should avoid in release version.You should add #if DEGUG XXX #endif.</Resolution>
<Email />
<MessageLevel Certainty="99">Error</MessageLevel>
<FixCategories>Breaking</FixCategories>
<Owner />
</Rule>
</Rules>
 AvoidNUnitTestCase.cs实现
public class AvoidNUnitTestCase : BaseIntrospectionRule
 {
public AvoidNUnitTestCase() : base("AvoidNUnitTestCase","Cnblogs.Rules.RuleInfo",typeof(AvoidNUnitTestCase).Assembly)
 {
}

public override ProblemCollection Check(TypeNode type)
 {
 if( DoesImplementConditionAttribute(type.Attributes)){
Resolution resolution = GetResolution(RuleUtilities.Format(type));
Problem problem = new Problem(resolution,type);
Problems.Add(problem);
return Problems;
}
return null;
}

private bool DoesImplementConditionAttribute( AttributeList Lists )
 {
Log.WriteFile( Lists.Length.ToString());
 for(int i=0;i<Lists.Length;i++){
 if( Lists[i].Type.FullName.Equals("NUnit.Framework.TestFixtureAttribute")){
return true;
}
}
return false;
}
} 编译成一个dll..加入到FxCop的Rules中,这样我们就可以很方便的每日Build后检测Release版本是否存在TestCase:) All Happy~:)
2005年4月3日
有好长时间没有写过Blog了...具体的原因真是一大堆啊,不说也罢,反正,偶现在是回来了:) 嘿嘿.
The Return of the hBifTS.
这几天一直在玩SubVersion,据说是比CVS更加好用的,更加强大的版本控制系统... 它的优点有很多,具体就不在这里介绍了.随便Google一把,都会有一大堆的:)
SubVersion的Server的实现有两种形式,一种就是和Apache的集成,可以实现http/https的访问.而且还可以很方便的通过Apache的集成来实现Per-Directory的认证. 另一种方式就是使用svnserve.exe.这是SubVersion内置的服务器.使用起来要比与Apache要方便,快捷很多. 其功能也相差不了多少(厄,还是相差很多的.)
现在的一个问题就是使用svnserve的方式,不支持Per-Directory的权限认证. 让我们来考虑一下怎么实现Per-Directory的权限认证. 实现这样的方式,我们得得到当前提交者的UserName,然后就是提交者的提交的路径.有了这两个,就可以通过相应的权限规则来判断是否有权限提交到些目录下面.最后一个就是能确认提交或是取消提交,否则权限控制完全没有意义了:)
由于Svn是用C/C++写的,而且提供了相应的.h文件,便于二次开发/增加插件功能.但是对于C#而言,就是一个恶梦(想想成堆的结构的声明,函数的导入),幸好SubVersion提供了Hooks Script,可以让我们在Start-commit/pre-commit/post-commit的时候做我们想做的事.既然这样,实现一个类似Per-Directory的认证就不是很困难了:)
打开一个生成的SubVersion的代码仓库,在目录下面有一个Hooks的目录,进去,我们可以看到5个文件. 打开Pre-commit.tmpl文件看看说明:
# The pre-commit hook is invoked before a Subversion txn is
# committed. Subversion runs this hook by invoking a program
# (script, executable, binary, etc.) named 'pre-commit' (for which
# this file is a template), with the following ordered arguments:
#
# [1] REPOS-PATH (the path to this repository)
# [2] TXN-NAME (the name of the txn about to be committed) 由上面的说明可得知,当Svn收到了用户提交上来的文件,在最终存入Repository前,会调用Pre-commit.exe/bat程序.同时传两个参数进去,一个就是提交的Repository的路径(服务器端的实际路径),第二个就是TXN-Name. Transaction Name,这个是用于标识此提交进程的事务ID. 有了上述的两个参数.再加上Svnlook.exe.我们就可以完成我们想做的事了~ 先来看看Svnlook.exe的帮助.
Name
svnlook author — Print the author.

Synopsis
svnlook author REPOS_PATH
Description
Print the author of a revision or transaction in the repository.

Switches
--revision (-r)
--transaction (-t)

Examples
svnlook author is handy, but not very exciting:

$ svnlook author -r 40 /usr/local/svn/repos
sally

 通过Repository的路径和TXN可以得到当前提交者的UserName.
Name
svnlook changed — Print the paths that were changed.

Synopsis
svnlook changed REPOS_PATH
Description
Print the paths that were changed in a particular revision or transaction, as well as an “svn update-style” status letter in the first column: A for added, D for deleted, and U for updated (modified).

Switches
--revision (-r)
--transaction (-t)

Examples
This shows a list of all the changed files in revision 39 of a test repository:

$ svnlook changed -r 39 /usr/local/svn/repos
A trunk/vendors/deli/
A trunk/vendors/deli/chips.txt
A trunk/vendors/deli/sandwich.txt
A trunk/vendors/deli/pickle.txt

 同上,可以得到当前提交者提交的内容以及提交类型. 呵呵,到了这里,实现权限控制的思路应该完全清楚了:) 1,通过Pre-commit.exe得到 Repository和TXN. 2,通过Svnlook.exe分别得到UserName和CommitContents 3,对UserName和CommitContents中的提交路径以及权限规则分析. 4,如果有权限提交,返回0.否则返回非0的值. TestSvnAuth.zip这里是我实现的一个权限控制,当然了,没有完全实现Per-Directory的权限认证.不过我想做为我自己来使用已够了:) config.ini是配置文件,要和pre-commit.exe放置于同一目录下面. [Config] BaseDirectory = Cnblogs/Helper/ 指明所有的用户只能在Cnblogs/Helper/路径下面提交/修改/删除文件.(注:此路径应该在svn repository中存在) [Allow] hbifts = dudu,steven 表明dudu和steven可以在hbifts用户的目录下面(包含子目录)即: Cnblogs/Helper/hbifts/ 进行修改. [Deny] Accounts = hbifts,dudu 表明hbifts和dudu不允许在此Repository中进行任何修改,提交任何文件. 注: Deny比Allow的优先级要高.由于测试的关系,我将所有的函数调用记录写入了一个.txt文件中,各位测试的时候请自行去掉些函数或修改log文件路径.由于每提交一次此程序会运行一次,从性能方式考虑,未使用xml文件做为配置文件. Wish have a good day~
|