加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – DSL提取案例类字段名称

发布时间:2020-12-16 18:02:00 所属栏目:安全 来源:网络整理
导读:我正在尝试构建一个DSL,但我遇到了一个问题:它适用于案例类,但我想知道提取案例类字段名称的最简单方法.我想到的一个想法是使用宏来丰富我的Case类的类型,但我不愿意. trait QueryDSL[CC] { def meta: CC implicit object StringIsFieldType extends Field[
我正在尝试构建一个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")

我想query.clauses等于:List(EqClause(displayName,Hallo))
现在它等于:
列表(EqClause(别名真实,你好))

解决方法

一些想法

鉴于我正确设法跟踪转换流程.你的最后一行

import Testing._
val query = Testing setProperty(_.displayName eqs "Hallo")

将QueryDSL的含义纳入范围.为了让Testing获取方法setProperty,它将使用implQuery转换为Query.然后displayName,为了获取方法eqs使用implField转换为QueryField,implField本身需要一个类型为Field [TestingCaseClass,String]的隐式值.在范围中确实存在此类型的值:StringIsFieldType.它扩展到

val query = Testing.implQuery[QueryDSL[TestingCaseClass]](Testing).setProperty {
 (cc : TestingCaseClass) => Testing.implField[String](cc.displayName)(Testing.StringIsFieldType).eqs("Hallo")
}

我想你想要的东西

trait Field[CaseClassType,FieldName] {
  type typeOfThisField
}

其中FieldName是单例文字类型String(name)(编译器中的有效类型,但我认为只能使用宏表示).

也许你正在寻找什么

使用无形2.2.5及其singleton-typed-literals的实现:

import shapeless._

// Clauses

abstract class Clause[V](val fieldName: String,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] = 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")
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读