J'écris un service RPC basé sur la réflexion qui obtient les arguments transmis via une variété de mécanismes. Parfois, les arguments correspondent correctement au type de paramètre, parfois ce sont toujours des chaînes, et parfois ils sont enveloppés dans des objets "script" dynamiquement typés qui nécessitent l'extraction de la valeur appropriée.Méthode efficace pour convertir des objets inconnus en arguments Method.invoke appropriés?
Avant que je puisse method.invoke appeler, je dois construire la liste des arguments, quelque chose comme ceci:
Object a[] = new Object[method.parameterClasses.length];
for (int i = 0; i < a.length; ++i)
{
a[i] = prepare(method.parameterClasses[i], rpc.arguments[i]);
}
La méthode « préparer » ressemble à quelque chose comme:
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!
}
}
Au cours de tests unitaires , J'ai récemment été plutôt surpris de découvrir qu'une méthode passée un Integer en boîte qui s'attendait à une primitive longue échouait en fait la distribution et tombait par le bas, puis était correctement convertie par quelque chose pendant l'invocation(). Je supposais que l'appel à «jeter» ferait l'affaire. Existe-t-il un moyen d'exécuter et de vérifier explicitement la conversion d'argument effectuée normalement par invoke? En l'absence de cela, j'ai pensé mettre des contrôles explicites pour les types numériques, mais le nombre de permutations semblait hors de contrôle. Lorsque j'ajoute un support pour extraire des nombres des types dynamiques de script et convertir des chaînes, cela devient encore pire. J'envisage un tas de typechecks conditionnels pour chaque classe cible numérique possible, avec Integer.decode, Long.decode etc pour les arguments String, Short.decode et Number.intValue, Number.longValue, etc. pour les nombres.
Y a-t-il une meilleure façon de faire tout cela? Cela semblait une bonne approche au début, mais ça devient plutôt dégueulasse.
Les conversions sensibles contraintes sont mon but, mais je dirais que les types numériques sont un domaine qu'il devrait être aussi flexible que possible, et juste la gestion de ceux-ci devient incontrôlable! –
BTW, merci pour cette idée ... Je regarde les règles JSPEL .. et bien sûr, c'est une longue liste ennuyeuse de conversions conditionnelles. Soupir. Eh bien, j'aurais probablement pu l'écrire dans le temps qu'il m'a fallu pour taper cette question. :-) –