airframe-surface enables reading type information, such as:
- Constructor parameter names and their types
- Methods defined in an object with method argument names and types.
build.sbt
libraryDependencies += "org.wvlet.airframe" %% "airframe-surface" % "(version)"
// For Scala.js
libraryDependencies += "org.wvlet.airframe" %%% "airframe-surface" % "(version)"Surface.of[X]returns parameters,MethodSurface.of[X]returns the list of methods inXand their parameter names and types.- airframe-surface is compatible between Scala and Scala.js
Applications of Surface include:
- Writing object serializer / deserializer without any boilerplates.
- For example, airframe-codec Automatically generates code serialiation and deserizliation using Surface.
- Dependency injection based on object shapes (e.g., Airframe DI)
- airframe-di detects dependent types using Surface
- Surface can be an indentifer of object types and type aliases.
Initial design note: Surface Design Document
import wvlet.airframe.surface.Surface
case class A(id:Int, name:String)
val s = Surface.of[A]
println(s.toString) // This will show A(id:Int, name:String)
// Find object parameters
s.params.mkString(", ") // Returns "id:Int, name:String"
// Object factory
s.objectFactory.map{ f =>
f.newInstance(Seq(1, "leo"))
}
// Some(A(1, "leo"))
type UserName = String
Surface.of[UserName] // Returns UserName:=String
To have different surfaces for the same type, you can use tagged type (@@):
import wvlet.airframe.surface.Surface
import wvlet.airframe.surface.tag._
class Fruit
trait Apple
trait Banana
Surface.of[Fruit @@ Apple]
Surface.of[Fruit @@ Banana]Reading runtime-annotation is supported for JVM projects. Import wvlet.airframe.surface.reflect._ to use this feature.
import wvlet.airframe.surface.Surface
import wvlet.airframe.surface.reflect._
import javax.annotation.Resource
@Resource(name="my resource")
class A(@Resource(name = "param 1") a:String)
val s = Surface.of[A]
// Reading class annotation
val a = s.findAnnotationOf[Resource]
a.get.name // "my resource"
// Reading parameter annotation
val r = s.params.find(_.name == "a").findAnnotationOf[Resource]
r.get.name // "param 1"