Scala中使用案例类的DSL [英] DSL in scala using case classes

查看:86
本文介绍了Scala中使用案例类的DSL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的用例具有类似

 case class Address(name:String,pincode:String){
    override def toString =name +"=" +pincode
  }

 case class Department(name:String){
   override def toString =name
 }

 case class emp(address:Address,department:Department)

我要创建如下所示的DSL。任何人都可以共享有关如何创建DSL的链接以及实现以下目标的任何建议。

I want to create a DSL like below.Can anyone share the links about how to create a DSL and any suggestions to achieve the below.

 emp.withAddress("abc","12222").withDepartment("HR")

更新:
实际用例类可能有更多接近20的字段。我想避免重复代码

Update: Actual use case class may have more fields close to 20. I want to avoid redudancy of code

推荐答案

我使用反射创建了DSL,因此我们无需向其添加每个字段。

I created a DSL using reflection so that we don't need to add every field to it.

Disclamer: DSL的输入类型非常弱,我只是为了好玩而已。我真的不认为这是Scala中的好方法。

Disclamer: This DSL is extremely weakly typed and I did it just for fun. I don't really think this is a good approach in Scala.

scala> create an Employee where "homeAddress" is Address("a", "b") and "department" is Department("c") and that_s it
res0: Employee = Employee(a=b,null,c)

scala> create an Employee where "workAddress" is Address("w", "x") and "homeAddress" is Address("y", "z") and that_s it
res1: Employee = Employee(y=z,w=x,null)

scala> create a Customer where "address" is Address("a", "b") and "age" is 900 and that_s it
res0: Customer = Customer(a=b,900)

最后一个示例等效于写作:

The last example is the equivalent of writing:

create.a(Customer).where("address").is(Address("a", "b")).and("age").is(900).and(that_s).it

在Scala中编写DSL并避免使用括号的方式是通过遵循以下模式进行的: / p>

A way of writing DSLs in Scala and avoid parentheses and the dot is by following this pattern:

object.method(parameter).method(parameter)...

此处是来源:

// DSL

object create {
  def an(t: Employee.type) = new ModelDSL(Employee(null, null, null))
  def a(t: Customer.type) = new ModelDSL(Customer(null, 0))
}

object that_s

class ModelDSL[T](model: T) {
  def where(field: String): ValueDSL[ModelDSL2[T], Any] = new ValueDSL(value => {
    val f = model.getClass.getDeclaredField(field)
    f.setAccessible(true)
    f.set(model, value)
    new ModelDSL2[T](model)
  })

  def and(t: that_s.type) = new { def it = model }
}

class ModelDSL2[T](model: T) {
  def and(field: String) = new ModelDSL(model).where(field)

  def and(t: that_s.type) = new { def it = model }
}

class ValueDSL[T, V](callback: V => T) {
  def is(value: V): T = callback(value)
}

// Models

case class Employee(homeAddress: Address, workAddress: Address, department: Department)

case class Customer(address: Address, age: Int)

case class Address(name: String, pincode: String) {
  override def toString = name + "=" + pincode
}

case class Department(name: String) {
  override def toString = name
}

这篇关于Scala中使用案例类的DSL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆