【问题标题】:Remove/Modify domain property using metaclass使用元类删除/修改域属性
【发布时间】:2016-01-14 19:34:39
【问题描述】:

有一个包含静态属性的域:

public static fieldNames = ['fieldName','fieldName2']

代码是:

def fieldNamesProperty = grailsApplication.getDomainClass("domainPackage....domain").getPropertyValue('fieldNames')

if(fieldNamesProperty){

// do something

} else{

// do something

}

在 spock 测试中,我想测试 else 部分,但我不能直接更改域,所以我想使用元类从域名中删除 fieldNames 属性或将其设置为 null 仅用于测试。可能吗 ?我知道如何使用元类覆盖方法,但不知道删除/覆盖属性。

更新:

    DomainClass.metaClass.static.getFieldNames = { ['category'] }
    def fieldNameProperty = grailsApplication.getDomainClass("...DomainClass").getPropertyValue('fieldNames')

返回空值

也试过了:

DomainClass.metaClass.getFieldNames = { ['category'] }
DomainClass className = new DomainClass()
println className.fieldNames

抛出missingPropertyException

也试过不使用 .static。

【问题讨论】:

    标签: grails groovy metaprogramming


    【解决方案1】:

    因为 Groovy 属性,就其属性而言,具有 getter 和 setter 方法,您可以使用 MetaClass 覆盖 getter 方法。

    带域类

    SomeClass.metaClass.static.getFieldNames = { [] }
    

    这是一个使用普通 Groovy 类的演示,您可以将其改编为 Grails 域类。

    class SomeClass {
        static fieldNames = ['fieldName','fieldName2']
    }
    
    SomeClass.metaClass.static.getFieldNames = { [] }
    
    def fieldNamesProperty = SomeClass.fieldNames
    
    if(fieldNamesProperty) println 'Got some field names'
    else println 'No field names'
    

    在本例中,将执行 else 分支,因为空列表的计算结果为 false

    使用 GrailsDomainClass

    如果需要grailsApplication.getDomainClass() 返回的GrailsDomainClass,则需要使用不同的方法。因为这不仅会影响特定的域类,因此最好不要使用 MetaClass。相反,我将使用一个类别。

    import org.grails.core.AbstractGrailsClass
    
    def klass = grailsApplication.getDomainClass("domainPackage....domain")
    
    def fieldNamesProperty = use(GrailsClassCategory) { klass.getPropertyValue('fieldNames') }
    
    class GrailsClassCategory {
        static Object getPropertyValue(AbstractGrailsClass klass, String name) {
            return ['fieldName','fieldName2']
        }
    }
    

    类别用于覆盖AbstractGrailsClass.getPropertyValue()

    【讨论】:

    • +1 我会试试这个。还有一种情况。另一个域不包含属性 fieldNames。但我必须动态添加它,以便代码 grailsApplication.getDomainClass("domainPackage....domain").getPropertyValue('fieldNames') 返回一些值。
    • 同样的方法也可以。返回一个包含值的列表,而不是一个空列表:SomeClass.metaClass.static.getFieldNames = { ['fieldname'] }
    • 我试过了,它不起作用。 grailsApplication.getDomainClass("domainPackage....domain").getPropertyValue('fi‌​eldNames') 返回 null。甚至在实例级别尝试过,但没有。
    • 请在问题中添加不起作用的代码,以便我知道它在哪里失败。
    • getDomainClass() 碍事了。它返回 DefaultGrailsDomainClass 而不是实际的域类。然后它使用ClassPropertyFetcherPropertyFetcher 来检索属性值。现在我的头在旋转,我问:为什么?是否有理由使用它而不是直接访问域类?
    猜你喜欢
    • 2019-11-05
    • 2012-07-20
    • 2016-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-13
    相关资源
    最近更新 更多