gpt4 book ai didi

java - 一种在运行时查找另一个对象(其中包含列表)的所有子对象的方法

转载 作者:行者123 更新时间:2023-12-01 11:41:13 25 4
gpt4 key购买 nike

我有一个项目,它基于 XML 架构,该架构可能会发生变化。使用 JAXB 将架构转换为 Java。模式的几个部分保证保持不变;特别是,用户必须填写的表单的基本元素。

我将根据这个(可能会更改)JAXB 生成的代码生成一个表单。问题是,因为我的代码是不变的,但架构可以随时更改,所以我无法在任何 JAXB 代码中进行硬编码,基本元素除外。

因此,我必须递归地查找基础对象下面的所有元素。这根本不是太麻烦,只需一点反射魔法(找到所有对象的“getter”方法的返回类型,重复)。真正的问题是当我遇到一个列表时。由于列表在运行时丢失其类型,因此我无法确定列表包含的内容,并且无法进一步递归。

有人有解决这个问题的绝妙解决方案吗?我已经研究了几乎所有其他在运行时保留列表类型的方法,但没有一个有效。我很清楚这可能是不可能的,但我想在放弃之前探索所有的选择。如果有其他方法可以做到这一点,我愿意尝试。

我当前的代码:

public static void getObjectDescendants(Object obj, int indent) throws Exception {
// Handle list of objects.
if (obj instanceof List) {
for(int i=0;i<indent;++i){System.out.print(" ");}
System.out.println("List");
Class<?> clazz = getListType((List<?>) obj); // Get type of object within list

// Create new object of that type from constructor. (temp solution)
Object object = clazz.getConstructor().newInstance();

getObjectDescendants(object, indent+1);
return;
}

// Handle regular object.
for (MethodDescriptor pd : Introspector.getBeanInfo(obj.getClass()).getMethodDescriptors()) {
// For each method this object has...
Method method = pd.getMethod();

// If it does not return a complex object, or a list, we don't care about it.
if (!method.getReturnType().toString().contains("JAXB.generated.object")
&& !method.getReturnType().toString().contains("java.util.List")) {
continue;
}

// Print out indent, and name of method.
for(int i=0;i<indent;++i){System.out.print(" ");}
System.out.println(method.getDeclaringClass().getSimpleName() + "." + method.getName() + "()");

Object object;
try {
if (method.getReturnType().equals(List.class)) {
object = method.invoke(obj);
} else {
Constructor<?> constructor = method.getReturnType().getConstructor(String.class);
object = constructor.newInstance();
}
} catch (Exception e) {
continue; // Couldn't seem to handle this one.
}

getObjectDescendants(object, indent+1);
}
}

private static Class<?> getListType(final List<?> list) {
// Find out what object type is in the list, and return it.
Class<?> clazz = list.get(0).getClass(); // Doesn't work, since list is always empty.
return clazz;
}

最佳答案

您可以使用 JAXB 模型,而不是反射到 JAXB 类。当您从类或包创建 JAXB 上下文时,它会创建这些类及其属性的基础模型。在运行时 - 基于注释。在编译时 (XJC) - 基于 XML 架构。

这是特定于实现的,因此我将采用 JAXB RI,因为我比 MOXy 更了解它。

  • 当您使用 JAXB RI 创建 JAXBContext 时,您将在最后获得一个 JAXBContextImpl 实例。
  • 它有一个 getTypeInfoSet() 方法,返回 RuntimeTypeInfoSet 的实例。
  • 这个 RuntimeTypeInfoSet 是 JAXB 类、属性的完整模型 - 编码和解码所需的一切。
  • 对于复杂类型,您将拥有具有属性 (RuntimePropertyInfo) 的 RuntimeClassInfo 实例

您可以分析这些结构并在运行时构建您的 UI。这比挖掘反射要容易得多。基本上这个 Runtime... 东西做了下面所有必要的反射,所以你不必这样做。

顺便说一句,我个人不会在这里重新发明轮子并采用现有的模型驱动 UI 生成方法之一,例如 Metawidget 。您必须将框架连接到 JAXB 模型,但这似乎比从头开始完成整个事情更容易。

大约 7-8 年前,我实现了基于 JAXB 的 XML 模式驱动的 UI 生成,这真是一次冒险。有很多注意事项。

关于java - 一种在运行时查找另一个对象(其中包含列表)的所有子对象的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29506684/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com