Roc*_*och 4 dsl scala implicit case-class scala-macros
我正在尝试构建DSL,但我遇到了一个问题:它适用于案例类,但我想知道提取案例类字段名称的最简单方法.我想到的一个想法是使用宏来丰富我的Case类的类型,但我不愿意.
trait QueryDSL[CC] {
def meta: CC
implicit object StringIsFieldType extends Field[CC, String] {
def name = "FakeNAME"
}
implicit def implQuery[V](b: V): Query[CC] = new Query[CC](meta)
implicit def implField[V](b: V)(implicit ev: Field[CC, V]): QueryField[CC, V] = new QueryField(ev)
}
case class Query[CC](meta: CC, clauses: List[Clause[_]] = Nil) {
def setProperty[F](clause: CC ? Clause[F]): Query[CC] = copy(clauses = clause(meta) :: clauses)
}
trait Field[V, M] extends scala.AnyRef {
def name: scala.Predef.String
}
abstract class Clause[V](val fieldName: String, value: V)
case class EqClause[V](override val fieldName: String, value: V) extends Clause[V](fieldName, value)
class QueryField[CC, M](field: Field[CC, M]) {
def eqs(v: M) = EqClause(field.name, v)
}
/// #################
case class TestingCaseClass(displayName:String = "Bonjour", active:Boolean = false)
object Testing extends QueryDSL[TestingCaseClass] {
def meta = new TestingCaseClass
}
import Testing._
val query = Testing setProperty(_.displayName eqs "Hallo")
Run Code Online (Sandbox Code Playgroud)
我想query.clauses等于:List(EqClause(displayName,Hallo))现在它等于:List(EqClause(FakeNAME,Hallo))
小智 5
鉴于我正确设法跟踪转换流程.你的最后一行
import Testing._
val query = Testing setProperty(_.displayName eqs "Hallo")
Run Code Online (Sandbox Code Playgroud)
带来影响QueryDSL范围.为了Testing获得方法,setProperty它被转换为Query使用implQuery.然后displayName,为了将get方法eqs转换为一个QueryFieldusing implField,它本身需要一个隐式的type值Field[TestingCaseClass, String].这种类型的确有一个值在范围内:StringIsFieldType.它扩展到
val query = Testing.implQuery[QueryDSL[TestingCaseClass]](Testing).setProperty {
(cc : TestingCaseClass) => Testing.implField[String](cc.displayName)(Testing.StringIsFieldType).eqs("Hallo")
}
Run Code Online (Sandbox Code Playgroud)
我想你想要的东西
trait Field[CaseClassType, FieldName] {
type typeOfThisField
}
Run Code Online (Sandbox Code Playgroud)
这里FieldName将是单文本类型String(name)(在编译器有效的类型,但我认为这是唯一使用宏可表达).
使用无形2.2.5及其单例类型文字的实现:
import shapeless._
// Clauses
abstract class Clause[V](val fieldName: String, value: V)
case class EqClause[V](override val fieldName: String, value: V) extends Clause[V](fieldName, value)
// Fields
sealed abstract class Field[CC, FieldName] {
// The name of the field
val fieldName: String
// The type of the field
type fieldType
// How to extract this field
def get(cc : CC) : fieldType
}
object Field {
// fieldType is existencial in Field but parametric in Fied.Aux
// used to explict constraints on fieldType
type Aux[CC, FieldName, fieldType_] = Field[CC, FieldName] {
type fieldType = fieldType_
}
def apply[CC, fieldType_](fieldWitness : Witness.Lt[String], ext : CC => fieldType_) : Field.Aux[CC, fieldWitness.T, fieldType_] =
new Field[CC, fieldWitness.T] {
val fieldName : String = fieldWitness.value
type fieldType = fieldType_
def get(cc : CC) : fieldType = ext(cc)
}
}
// Queries
case class Query[CC](meta: CC, clauses: List[Clause[_]] = Nil) {
def setProperty[F](clause: CC ? Clause[F]): Query[CC] = copy(clauses = clause(meta) :: clauses)
}
class QueryField[CC, M](field: Field.Aux[CC, _, M]) {
def eqs(v: M) = EqClause(field.fieldName, v)
}
trait QueryDSL[CC] {
def meta: CC
implicit def implQuery[V](b: V): Query[CC] = new Query[CC](meta)
implicit def implField[fieldName, V](b: V)(implicit ev: Field.Aux[CC, fieldName, V]): QueryField[CC, V] = new QueryField(ev)
}
/// #################
object Example extends App {
case class TestingCaseClass(displayName:String = "Bonjour", active:Boolean = false)
implicit val displayName = Field(Witness("displayName"), (cc : TestingCaseClass) => cc.displayName)
implicit val active = Field(Witness("active") , (cc : TestingCaseClass) => cc.active )
object Testing extends QueryDSL[TestingCaseClass] {
def meta = new TestingCaseClass
}
import Testing._
val queryDisplayName = Testing setProperty(_.displayName eqs "Hallo")
println(s"queryDisplayName = $queryDisplayName")
val queryActive = Testing setProperty(_.active eqs true)
println(s"queryActive = $queryActive")
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
550 次 |
| 最近记录: |