我正在为Braintree Java库编写一个Clojure包装器,以提供更简洁和惯用的界面.我想提供快速简洁地实例化Java对象的函数,如:
(transaction-request :amount 10.00 :order-id "user42")
Run Code Online (Sandbox Code Playgroud)
我知道我可以明确地这样做,如这个问题所示:
(defn transaction-request [& {:keys [amount order-id]}]
(doto (TransactionRequest.)
(.amount amount)
(.orderId order-id)))
Run Code Online (Sandbox Code Playgroud)
但是这对于许多类来说是重复的,并且当参数是可选的时变得更复杂.使用反射,可以更简洁地定义这些函数:
(defn set-obj-from-map [obj m]
(doseq [[k v] m]
(clojure.lang.Reflector/invokeInstanceMethod
obj (name k) (into-array Object [v])))
obj)
(defn transaction-request [& {:as m}]
(set-obj-from-map (TransactionRequest.) m))
(defn transaction-options-request [tr & {:as m}]
(set-obj-from-map (TransactionOptionsRequest. tr) m))
Run Code Online (Sandbox Code Playgroud)
显然,如果可能的话,我想避免反思.我尝试定义一个宏版本,set-obj-from-map但我的宏功能不够强大.它可能需要eval为解释在这里.
有没有办法调用在运行时指定的Java方法,而不使用反射?
提前致谢!
更新的方案:
按照Joost的建议,我能够使用类似的技术解决问题.宏在编译时使用反射来识别类具有哪些setter方法,然后吐出表单以检查映射中的param并使用它的值调用该方法.
这是宏和示例用法:
; Find only setter methods that we care about
(defn find-methods …Run Code Online (Sandbox Code Playgroud) 我正在更新Amazon S3存储桶中的现有对象以设置一些元数据.我想Expires为每个对象设置HTTP 标头以更好地处理HTTP/1.0客户端.
我们正在使用AWS Java SDK,它允许对对象进行元数据更改,而无需重新上传对象内容.我们使用CopyObjectRequest将对象复制到自身.该ObjectMetadata类允许我们设置的Cache-Control,Content-Type和其他几个头.但不是Expires标题.
我知道S3 Expires使用REST API 存储并提供对象PUT 的标头.有没有办法从Java SDK中执行此操作?
更新以表明我们正在使用 CopyObjectRequest