DSL提取案例类字段名称

时间:2015-07-17 09:21:36

标签: scala dsl implicit scala-macros case-class

我正在尝试构建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(别名真实,喂))

1 个答案:

答案 0 :(得分:5)

一些想法

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

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

QueryDSL的含义纳入范围。要使Testing获取方法setProperty,请使用Query将其转换为implQuery。然后displayName,方法eqs使用QueryField转换为implFieldField[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)将是单例文字类型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") } (编译器中的有效类型,但我认为只能使用宏表达)。

也许你正在寻找什么

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

<?php    

$db = 'B5CGM';
$user='root';
$pw='147147';

//$user='root';
//$pw='';

$db_connect = mysql_connect("localhost", $user, $pw)
or die (mysql_error());

mysql_select_db($db, $db_connect);

$sql = "CREATE TABLE tac_flightsize
(

    entry int NOT NULL AUTO_INCREMENT,
    gameid int,    
    shipid int,
    flightsize int,

    PRIMARY KEY (entry),
 )";

mysql_query($sql, $db_connect);

echo "done";


?>