2011-03-03 32 views
15

我已经建立了许多枚举类与int getID()MyEnum withID(int)方法,允许我专用ID为枚举值的持久性目的(从而避免由于命令/名称更改有关外部存储的枚举)。春季自定义转换器的所有枚举

我想建立一个自定义转换器,它会做一些反射来查找这些方法,并在找不到这些方法时使用它们或备份到序数/字符串转换。

泛型Enum转换器对任何人都可能吗?这只是我第二次进入转换器。

+1

+1扩展。我特别喜欢你“避免因订单/姓名而发生的变化”_ – 2014-06-18 15:33:02

回答

15

我想说你正试图解决错误的问题。我通常坚持把枚举作为Strings,从而避免了这个问题。缺点当然是一个更大的数据库领域,但这并不重要。


这就是说:

我会说这是可能一般,但不是在一个干净的方式。我要做的就是让所有这些枚举实现一个通用接口(或者只是一个标记接口或一个包含int getId()方法的接口)。现在只需注册您的PropertyEditor,然后您就不会破坏太多的标准功能。

然后,你的下一个问题是你依靠静态工厂方法,这是不能用通用的方式完成的。当然,你的属性编辑器可以做:

enumClass.getDeclaredMethod("withId", int.class).invoke(id) 

但我称之为非常哈克。怎么样是这样的:

Object target = null; 
for(Object e : EnumSet.allOf(yourEnumClass)){ 
    if(e instanceof MyInterface && ((MyInterface)e).getId()==thisId){ 
     target = e; 
     break; 
    } 
} 
return target; 

现在你没有使用任何静态工厂方法,你有编译时的安全性,只要你的枚举实现一个共同的接口。


更新:新转换器SPI变得越来越容易。使用a custom ConverterFactory

public class CustomEnumConverterFactory implements 
    ConverterFactory<String, Enum<?>>{ 

    @Override 
    public <T extends Enum<?>> Converter<String, T> getConverter(
     final Class<T> targetType){ 
     return WithId.class.isAssignableFrom(targetType) 
      ? new EnumWithIdConverter(targetType) 
      : new StandardEnumConverter(targetType); 
    } 

} 

注册这样的:

<bean id="conversionService" 
    class="org.springframework.context.support.ConversionServiceFactoryBean"> 
    <property name="converters"> 
     <!-- converters is a set of both converters and converterfactories --> 
     <bean class="foo.bar.CustomEnumConverterFactory" /> 
    </property> 
</bean> 
+0

杰出的回应。谢谢!一个问题,Converter接口似乎没有给我任何方式来知道它试图将字符串转换为什么样的枚举类型。你提到Property Editors,我应该看看Property Editors,而不是试图在春季使用更新的Converter SPI?例如,值[1]可能对10个不同的Enum类有效。 – 2011-03-03 09:49:28

+0

@大卫哦,我的坏,我不太熟悉转换器SPI,我假设你的意思是一个PropertyEditor。让我检查:-) – 2011-03-03 09:51:34

+1

转换器SPI非常简单,您只需实现接口:Converter 并注册它。但是它声明的唯一转换方法只传入FromClass并且期望您派生ToClass。因此没有传入Enum 或类似的东西。我想也许财产编辑提供了一种处理事物的不同方式。我从来没有看过他们。 – 2011-03-03 10:01:48

0

从WebMvcConfigurerAdapter

@Override 
@SuppressWarnings("unchecked") 
public void addFormatters(FormatterRegistry registry) { 
    registry.addConverterFactory(new ConverterFactory<String, Enum>() { 
     @Override 
     public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) { 
      return source -> { 
       try { 
        return (T) Enum.valueOf(targetType, source); 
       } catch (Exception e) { 
        return targetType.getEnumConstants()[Integer.parseInt(source)]; 
       } 
      }; 
     } 
    }); 
    super.addFormatters(registry); 
}