mercredi 9 août 2017

How to dinamically add all methods of a class on another class

I have a global shared library on Jenkins implicitly loaded on all pipelines, then my Jenkinsfile is like that:

new com.company.Pipeline()()

And then the shared library has on directory src/com/company some files, below the Pipeline.groovy class:

package com.company  

import static Utils.*

def call() {
  // some stuff here...
}

The problem is, this way I have to static declare all methods, thus I lose the context and cannot access jenkins' methods easly without the Pipeline class' instance. As you can see here they passing this to the method mvn.

Thinking about avoid it I was wondering about dynamically add all methods as closures by calling Utils.install this instead of using import static Utils.*, then my Utils.groovy is something like that:

package com.company

private Utils() {}

static def install(def instance) {
  def utils = new Utils()
  // Some extra check needed here I know, but it is not the problem now
  for (def method in (utils.metaClass.methods*.name as Set) - (instance.metaClass.methods*.name as Set)) {
    def closure = utils.&"$method"
    closure.delegate = instance
    instance.metaClass."$method" = closure
  }
}

def someMethod() {
  // here I want to use sh(), tool(), and other stuff freely.
}

But it raises an GStringImpl cannot be cast to String error, I believe .& do not work with variables, how can I convert a method into closure? I have the MetaMethod interface mostly being a CachedMethod instance, if it were possible to turn it a ClosureMetaMethod instance maybe the problem can be solved, but whenever I search for method to closure conversion for groovy I just found the .& solution!

If I use instance.metaClass.someMethod = utils.&someMethod it do work, but I want it to be dinamic as I add new methods without needing to worry about sharing it.





Aucun commentaire:

Enregistrer un commentaire