Я разрабатываю небольшую DSL в Groovy, и мне было интересно, есть ли способ заставить заказ в вызовах метода.Порядок вызова метода метода в Groovy DSL
Например, это было бы справедливо
SensorDSL.camera {
take "picture" store_in "path" on {
success "mySuccessCallback"
cancel "myCancelCallback"
error "myErrorCallback"
}
}
но писать store_in
перед тем take
метод не должен быть разрешен.
Вот мой текущий код.
class SensorDSL {
def static camera(@DelegatesTo(CameraHandler) Closure closure){
CameraHandler delegate = new CameraHandler()
def code = closure.rehydrate(delegate, null, null)
code.resolveStrategy = Closure.DELEGATE_ONLY
code()
}
}
class CameraHandler {
String mediaType
String path
CameraCallbackHandler callbackHandler
public CameraHandler(){
callbackHandler = new CameraCallbackHandler()
}
CameraHandler take(String mediaType) {
if (!MediaType.values().collect{it.toString()}.contains(mediaType.toUpperCase())){
throw new Exception("Only PICTURE or VIDEO can be taken")
}
this.mediaType = mediaType
this
}
CameraHandler store_in(String path){
this.path = path
this
}
void on(@DelegatesTo(CameraCallbackHandler) Closure closure){
def code = closure.rehydrate(callbackHandler, null, null)
code.resolveStrategy = Closure.DELEGATE_ONLY
code.call()
}
class CameraCallbackHandler {
String successCallback
String errorCallback
String cancelCallback
CameraCallbackHandler success(String methodName){
this.successCallback = methodName
this
}
CameraCallbackHandler cancel(String methodName){
this.cancelCallback = methodName
this
}
CameraCallbackHandler error(String methodName){
this.errorCallback = methodName
this
}
}
}
Также было бы здорово, если есть способ сделать вызов метода без ручной проверки.
Редактировать: Я нашел способ, который, кажется, работает. Если возврат метода - это карта замыканий, вы можете вызвать методы в данном порядке. Например:
def take(String mediaType){
[store_in: {path->
this.path = path
[on: { Closure closure->
def code = closure.rehydrate(callbackHandler, null, null)
code.resolveStrategy = Closure.DELEGATE_ONLY
code.call()
}]
}]
}
Но возникает проблема, что нет автозавершения кода не дается в IDE (я использую IntelliJ). Есть ли другой способ заставить заказ, но поддерживать завершение кода в среде IDE?
Так как они просто объекты недвижимости, на самом деле, если вы не возвращаете контекстно-зависимые объекты. Например, 'store_in' возвращает экземпляр' PictureTaker' вместо того, чтобы вставлять все в 'CameraHandler'. Я бы поставил вопрос, действительно ли порядок здесь. –
Возможно, это не очень актуально в этом примере, но мне нужно сделать некоторые другие DSL, в которых было бы больше смысла форсировать заказ. – Eylen
Два простых варианта: (a) поддерживать конечный автомат, который обеспечивает порядок вызова, например, вы можете 't перейти от 'store_in' к' take' или (b) разбить некоторые классы. Есть некоторые внутренние ограничения для внутренних DSL; иногда лучше писать минимальный внешний DSL, когда контекст и семантика очень важны. –