计算属性的Groovy c#表达式等价
在.NET中,我们可以编写如下代码来返回propertyName计算属性的Groovy c#表达式等价,groovy,Groovy,在.NET中,我们可以编写如下代码来返回propertyName public static string GetName(Expression<Func<object>> exp) { MemberExpression body = exp.Body as MemberExpression; if (body == null) { UnaryExpression ubody = (UnaryExpression)exp.Body;
public static string GetName(Expression<Func<object>> exp)
{
MemberExpression body = exp.Body as MemberExpression;
if (body == null) {
UnaryExpression ubody = (UnaryExpression)exp.Body;
body = ubody.Operand as MemberExpression;
}
return body.Member.Name;
}
public class Test
{
public string prop1 { get; set; }
}
您将如何在groovy中使用如上所示的表达式实现getName方法?我认为最接近于提供此功能的方法完全是人为的、笨拙的、临时的。它依赖于Java Bean API,由Groovy
@Vetoable
注释提供便利,将大多数丑陋之处保留在类代码之外:
import groovy.beans.Vetoable
import java.beans.PropertyChangeEvent
import java.beans.PropertyVetoException
class TestObj {
@Vetoable def prop1 = "value"
@Vetoable def prop2 = "value"
}
def t1 = new TestObj()
def getName(def t, Closure c) {
def name
t.vetoableChange = { PropertyChangeEvent pce ->
if (!pce.newValue) { throw new PropertyVetoException("", pce) }
}
try { c.call() }
catch (PropertyVetoException e) { name = e.propertyChangeEvent.propertyName }
t.vetoableChange = { it -> }
name
}
def propertyName1 = getName(t1) { t1.prop1 = null }
def propertyName2 = getName(t1) { t1.prop2 = null }
assert propertyName1 == "prop1"
assert propertyName2 == "prop2"
哎呀 对我来说,这种方法最有益的用途是在编译时使用,这样这种代码就可以尽早中断,并且简单的字符串输入错误不会在运行时导致bug。在像groovy这样的高度动态的语言中,很难找到合适的方法引用来使用。下面是一些代码,它在运行时执行此操作,但是您从中得到的唯一东西是您正在控制的断言(在下面的代码中)。(
clazz.&something
不是您在java8或c++中使用的真正方法引用,例如clazz::getSomething
)。因此,这里有一些笨拙的尝试,试图滥用MethodClosure
,并做一个简单的检查,如果所属类在运行时有此的getter
class Clazz {
String username
String firstName
def lastName
String getFake() { return 'fake' }
void setSomething(String something) {}
}
String getName(org.codehaus.groovy.runtime.MethodClosure it) {
def m = it.method.toString()
assert it.delegate.respondsTo("get${m[0].toUpperCase()}${m[1..-1]}")
it.method.toString()
}
def c = new Clazz()
assert getName(c.&username) == 'username'
assert getName(c.&lastName) == 'lastName'
assert getName(c.&fake) == 'fake'
也就是说,我在代码示例中看到的是,在我看来,整个技术似乎可以帮助开发人员触发事件,以防止错误输入字符串。因此,可能有一个更为groovyier的解决方案来解决所有这些问题,只需使用,它将您的属性或类的所有属性转换为“根据JavaBeans规范绑定的属性”。这会为您生成整个属性更改模板代码,从而减少需要担心的代码。这是一个拦截器吗?如果有方法
Clazz.getwhere(字符串内容)
,则使用这种方法可能会得到误报。在这种情况下,该方法接受一个参数,因此不表示属性。但是,assert getName(c.&whater)==“whater”
仍然通过。可能在getName()
方法中有一个附加的断言,比如assert.parameterTypes.size()==0
order@BalRog是的,如果有什么东西,也可以检查所有者/委托的属性,这可能更容易,但需要一个find{}True dat。这里还有一个可能的bug。我还没有确定检查过,但是我认为如果属性名是单个字符,子表达式${m[1..-1]}
将抛出某种“索引超出范围”异常。过去我不得不使用一些笨拙的东西,比如${m[1..@BalRog,简而言之:as yuk as;)
class Clazz {
String username
String firstName
def lastName
String getFake() { return 'fake' }
void setSomething(String something) {}
}
String getName(org.codehaus.groovy.runtime.MethodClosure it) {
def m = it.method.toString()
assert it.delegate.respondsTo("get${m[0].toUpperCase()}${m[1..-1]}")
it.method.toString()
}
def c = new Clazz()
assert getName(c.&username) == 'username'
assert getName(c.&lastName) == 'lastName'
assert getName(c.&fake) == 'fake'