Scala trait mixins for / typesafe Config object

This is the OO design of Q. I am using Configate Config in my application. The Config interface is very useful, but there are several fields in my applications; configuration file, which is required. I would like to create a subInterface Config and add these 2 top level methods. Something like that

trait AppConfig extends Config{ def param1:String def param2:String } 

However, creating a real instance of AppConfig based on the Config instance is not possible (I do not want to create a wrapper object and duplicate all methods in the Config interface). Ideally, Im looking for something that will achieve something close to this.

 val conf:Config = //get config object from somewhere return conf with AppConfig { overrider def param1 = {"blah"} } 

I understand that the last line is invalid. But Im looking for a template / construct with equivalent functionality.

+4
source share
3 answers

What you are looking for is basically what some call a “dynamic mixin”. This is not supported from scala. Someone developed a compiler plugin to support this: http://www.artima.com/weblogs/viewpost.jsp?thread=275588

However, this is a bit outdated and the project no longer looks active.

A better alternative would be to implement this function using scala macros (requires scala 2.10, which does not yet have a stable version).

All this is probably too tiring in your case. Until some well-tested library is available, I would suggest just creating a proxy server manually (no matter how boring it may look):

 trait ConfigProxy extends Config { def impl: Config // Forward to the inner config def root: ConfigObject = impl.root def origin: ConfigOrigin = impl.origin //... and so on } val conf:Config = //get config object from somewhere val myConf: AppConfig = new AppConfig with ConfigProxy { val impl = conf val param1:String = "foo" val param2:String = "bar" } 
+1
source

We used Configrity for such things. Here is an example:

We save our compiled defaults that we use for unit test / etc in objects

 object DefaultConfigs { val defaultConfig = Configuration( "param1" -> "blah" ) val otherConfig = Configuration( "param2" -> "blah" ) val appConfig = defaultConfig.include(otherConfig) } 

And then at runtime we can enable them or not

 val appConfig = Configuration.load(pathToConfig) include DefaultConfigs.appConfig 
+2
source

How about using a combination of Dynamic and Reflection. Dynamically processing your convenience and reflection methods to process methods in config.

Here is a hit:

 class ConfigDynamic(val config: Config) extends Dynamic { def selectDynamic(name: String)= { name match { case "field1" => config.getString("field1") case x @ _ => // overly simplified here val meth = configClass.getDeclaredMethod(x) meth.invoke(config) } } } 
+1
source

Source: https://habr.com/ru/post/1432635/


All Articles