|
该帖已经被评为精华帖
|
|
|---|---|
| 作者 | 正文 |
|
最后更新时间:2004-09-14
我除了用DotNet自身的attribute外, 也在项目里写过一些自定义的attribute class, 下面是我写的一个用attribute class来调用oracle stored proc的例子.
我有一个oracle package ”TestPkg”, 包括一个procedure “Get_Peoples” 我传一个company_id 给他, 他返回一个oralce ref_cursor, 里包含几行people记录。 我写了一个DAO, 代码基本上象这样 Class TestPkg : OraclePackageBase{ .. //定义Get_Peoples的OracleCommandMethodAttribute的meta data [OracleCommandMethod(CommandType.Text, CommandText = 'begin :function_result := TestPkg.. Get_Peoples (:company_id); end; ')] Public OracleDataReader Get_Peoples( //定义company_id的OracleParameterAttribute的meta data [OracleParameter (ParamType = OracleType.NUMBER, Size = 22)] int company_id ) OracleCommand FCmd: Object[] FParamValues = new Object[1]; //把参数放到一个array里 FParamValues[0] = company_id; //利用MethodInfo和参数array生成oraclecommand对象 FCmd = OracleCommandGenerator.Create().GenerateCommand(this.Connection, MethodInfo(MethodBase.GetCurrentMethod), FParamValues); FCmd.Transaction = this.Transaction; //调用oracle stored proc FCMD.ExecuteNonQuery(); //得到返回值 for (i = 0 ; FCMD.Parameters.Count ; i++) { if (FCMD.Parameters[i].Direction == ParameterDirection.Output) && (FCMD.Parameters[i].ParameterName == “function_result”) { return OracleDataReader(FCMD.Parameters[i].Value); } } } 这里用到我另外写的两个attribute class, OracleCommandMethodAttribute和OracleParameterAttribute. 和两个类OraclePackageBase和OracleCommandGenerator. OraclePackageBase类用来初始化一些环境变量,如connection, transaction啥的, 在DAO method里, 我传递MethodInfo 对象进OracleCommandGenerator.GenerateCommand方法, 在GenerateCommand方法里用OracleCommandMethodAttribute和OracleParameterAttribute得到并较验attribute meta data, 然后生成OracleCommand对象来调用oracle procedure. 并得到返回值 这样一来, DAO class里不同method的代码基本相同, 需要替换的只有以及class method的名字和参数和他上面附加的两个attribute的参数, 我就写了一个code generator根据oracle package来生成这个DAO. Oracle package的meta 信息来自oracle sys view “dba_source”, 我写了一个VS.net的plug-In去仿问这个view, 得到各stored procedure 名字和参数,用一个XSL文件保存DAO code template, 然后用上面得到oracle package的procedure 名字和参数替换掉template 里的动态variable, loop一下就可以了. 上面的code generator也可写成在runtime动态生成代码, Dotnet提供了codeDom类来动态生成代码,象java 里的CGLib, 不过考虑到效率和package变动问题, 我还是用code generator, 就象web sevice里处理wsdl一样。每当oracle package变动, 我只要用plugIn重生成新代码, build时IDE会告诉哪些调用code需修改. 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
最后更新时间:2004-09-14
代码生成绝对不是一个好的做法。为什么要有attribute?就是为了让你可以在runtime resolve一些metadata,避免依赖代码生成。
|
|
| 返回顶楼 | |
|
最后更新时间:2004-09-14
gigix 写道 代码生成绝对不是一个好的做法。为什么要有attribute?就是为了让你可以在runtime resolve一些metadata,避免依赖代码生成。
不能一概而论, 代码生成在某些情况使用下还是很好的, 前题是生成的代码在独立文件中, 不可手工修改, 比如在web service中无论java还是.net都用代码生成器利用wsdl生成client端proxy class, 我的这个例子也是用来生成oracle stored proc的client端proxy class。 这种方法在CORBA里也广泛用到 |
|
| 返回顶楼 | |
|
最后更新时间:2004-09-14
但是client端proxy根本不需要代码生成,只要用动态代理就可以了,你想想是不是这么个道理?总之client从某个工厂去取proxy,取到的是具有业务接口的一个动态代理,至于怎么调用远程方法,都在动态代理里做。你看看Hessian的ProxyFactory就知道了。
client端proxy是个很好的例子,它非常有力地说明:需要代码生成的大多数情况是Java 1.1或者1.2时的情况,当我们拥有动态代理之后,很多代码生成都是不必要的。 |
|
| 返回顶楼 | |
|
最后更新时间:2004-09-14
gigix 写道 但是client端proxy根本不需要代码生成,只要用动态代理就可以了,你想想是不是这么个道理?总之client从某个工厂去取proxy,取到的是具有业务接口的一个动态代理,至于怎么调用远程方法,都在动态代理里做。你看看Hessian的ProxyFactory就知道了。
client端proxy是个很好的例子,它非常有力地说明:需要代码生成的大多数情况是Java 1.1或者1.2时的情况,当我们拥有动态代理之后,很多代码生成都是不必要的。 动态代理会丢掉compile checking的优势, 想想我们为啥做daily build, 在大型项目里用动态代理绝对不是个好主意 |
|
| 返回顶楼 | |
|
最后更新时间:2004-09-14
这话奇怪了,动态代理怎么会丢掉compile checking呢?比如Hessian,我们首先定义一个接口:
[code:1] public interface IMyService { public void doSomething() { [/code:1] 然后实现server端: [code:1] public class MyServiceImpl extends HessianServlet implements IMyService { public void doSomething() { [/code:1] 最后client端这样进行RPC: [code:1] IMyService service = HessianProxyFactory.createProxy(url, IMyService.class); service.doSomething(); [/code:1] 请问,我在哪个环节上失去了compile checking?哪个环节不适合在大型项目使用? |
|
| 返回顶楼 | |
|
最后更新时间:2004-09-14
我问你, 你这个IMyService 是哪来的, 你这个doSomething() 又是那来的,
当你拿到一个别人的wsdl, 你怎样写个动态proxy出来 |
|
| 返回顶楼 | |
|
最后更新时间:2004-09-14
原来你的意思是使用外部的web service,那肯定要生成代码了,没办法的事。
|
|
| 返回顶楼 | |
|
最后更新时间:2004-09-14
gigix 写道 原来你的意思是使用外部的web service,那肯定要生成代码了,没办法的事。
外部内部有区别吗? |
|
| 返回顶楼 | |
|
最后更新时间:2004-09-14
当然有区别。如果是我自己的几个application之间需要remoting,我就可以在它们之间共享同样的Java接口,于是就变成我举的代码示例那样,不需要生成任何代码。
|
|
| 返回顶楼 | |





