2009-09-29 66 views
2

我正在写一个基于反射的RPC服务,它通过各种机制获取传入的参数。有时参数与参数类型正确匹配,有时候它们总是字符串,有时它们会被包含在动态类型的“脚本”对象中,这些对象需要提取出适当的值。将未知对象转换为适当的Method.invoke参数的有效方法?

之前,我可以打电话method.invoke,我需要建立参数列表,像这样:

Object a[] = new Object[method.parameterClasses.length]; 
for (int i = 0; i < a.length; ++i) 
{ 
    a[i] = prepare(method.parameterClasses[i], rpc.arguments[i]); 
} 

“准备”的方法看起来像是:

Object prepare(Class clazz, Object o) 
{ 
    if (o == null) return null; 
    if (clazz == o.getClass()) return o; 
    if (clazz == String.class) return o.toString(); 

    // skip a bunch of stuff for converting strings to dates and whatnot 

    // skip a bunch of stuff for converting dynamic types 

    // final attempts: 
    try 
    { 
     return clazz.cast(o); 
    } 
    catch (Exception e) 
    { 
     return o;  // I give up. Try the invoke and hope for the best! 
    } 


} 

在单元测试,我最近很惊讶地发现一个方法通过了一个盒装Integer,期望一个原始的长实际上是失败的演员,并通过底部,然后在invoke()期间正确转换的东西。我认为打电话给“演员”是可以做到的。有没有什么办法显式地执行和检查通常由invoke完成的参数转换?

缺乏这一点,我想过对数字类型进行明确的检查,但排列的数量似乎无法实现。当我添加从脚本动态类型提取数字和转换字符串的支持时,情况会变得更糟。我为每个可能的数字目标类设想了一系列条件类型检查,其中Integer.decode,Long.decode等用于Numbers的String参数,Short.decode和Number.intValue,Number.longValue等。

有没有更好的方法来做这件事?起初它似乎是一个很好的方法,但它变得相当糟糕。

回答

2

确实令人惊讶,但这是目前的行为。查看错误6456930

在一个更好的办法来解决这个问题方面,其核心是不,你必须定义所有的这些规则。尽管如此,有一系列更好(更可维护)的模式。对于初学者来说,我会为这些对象的一边(可能是类边)调用一些策略对象,以便根据类查找适当的对象(比如来自Map),然后可以限制你转换到一边(每个对象都会关心如何将事物放入特定的类)。这样,当你需要支持一种新的类转换时,你可以为它编写一个对象,单独测试它,并将其插入到地图中,而无需更改代码。

1

确实没有更好的方法。有无数的潜在转化,但只有一小部分是真正有意义的。我不建议为客户提供完全的自由,而是建议指定类型强制合同。

作为一个起点,请查看JSP Expression Language.使用的类型转换规则它们非常强大,允许进行多种类型的转换,但它们也定义明确,易于记忆,并且可以实现。

+0

约束合理的转换是我的目标,但我要说的却是数字类型是一个区域,它应该是尽可能的灵活,只是管理这些是失控! – 2009-09-29 19:43:08

+0

顺便说一句,谢谢你的想法......我正在看JSPEL规则..当然,这是一个很长的烦人的条件转换列表。叹。哦,我可能可以在写下这个问题的时候写下它。 :-) – 2009-09-29 19:47:50

0

有您可以采取简化代码至少有几个快捷键:

  • 如果参数是java.lang.Number中的一个实例和参数类型为字节,short,int和long,float或者double(或者作为primitive或者wrapper类),你可以使用Number中的方法如byteValue(),shortValue()等来转换参数。

  • 如果参数是java.lang.String的一个实例并且参数类型是上面提到的参数类型之一,那么可以在相应的类中使用静态valueOf(String)方法进行转换。

进一步转换,甚至私有类型当然需要更多的工作。如果真的有必要,而且您的准备方法越来越大,那么您可能应该考虑抽象化接口背后的转换,并允许可插入的转换提供程序动态添加到应用程序中?

相关问题