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

Scala中依赖注入的读者组成

发布时间:2020-12-16 09:04:49 所属栏目:安全 来源:网络整理
导读:这是一个简单的服务示例,其方法返回读者: trait Service1_1{ def s1f1:Reader[Map[String,Int],Int] = Reader(_("name")) def s1f2:Reader[Map[String,Int] = Reader(_("age"))} 这是一个服务使用者,它接受参数,map,并返回阅读器本身: trait Service1_2 {
这是一个简单的服务示例,其方法返回读者:

trait Service1_1{
  def s1f1:Reader[Map[String,Int],Int] =
    Reader(_("name"))

  def s1f2:Reader[Map[String,Int] =
    Reader(_("age"))
}

这是一个服务使用者,它接受参数,map,并返回阅读器本身:

trait Service1_2 {
  def s12f1(i:Int,map:Map[String,Int]):Reader[Service1_1,Int] =
    Reader(s => {
      val r = for {
        r1 <- s.s1f1
        r2 <- s.s1f2
      } yield r1 + r2
      r.run(map) + i
    })
}

好的,要使用Service1_2.s12f1我必须在参数列表中有map:

object s1 extends Service1_1
object s2 extends Service1_2
val r = s2.s12f1(3,Map("age"-> 1,"name"-> 2)).run(s1)

问题:如何实现Service1_2.s12f2:

trait Service1_2 {
  def s2f2 = ???
}

为了能够运行它:

s2.s2f2(2)
  .run(s1)
  .run(Map("age"-> 1,"name"-> 2))

主要思想是推迟将依赖关系传递给执行.这应该允许获得更好的组合和延迟执行.如何让它工作?如果存在具有此类依赖关系的嵌套调用,那么使用读者的最佳做法是什么?例如,想象服务Service1_3,它在一种方法中将同时使用Service1_2.s2f2和Service1_1.s1f1

更新,好吧,我可以实现它,但它看起来,复杂:

def s2f2(i:Int): Reader[Service1_1,Reader[Map[String,Int]] =
    Reader(s => Reader(map => {
      val r = for {
        r1 <- s.s1f1
        r2 <- s.s1f2
      } yield r1 + r2
      r.run(map) + i
    }))

问题是,有更好的方法吗?或至少语法?有几个级别的依赖,它会看起来很奇怪.

解决方法

我可能会“解开”读者,所以我没有两个(或更多)读者层,而是有一个n元组作为环境.然后,您可以将较小的读者“提升”到当前的当前级别.

例如,我使用Reader [(Service1_1,Map [String,Int]),Int]代替Reader [Service1_1,Reader [Map [String,Int]]:

import cats.data.Reader

trait Service1_1{
  def s1f1: Reader[Map[String,Int] = Reader(_("name"))
  def s1f2: Reader[Map[String,Int] = Reader(_("age"))
}

trait Service1_2 {
  type Env = (Service1_1,Map[String,Int])

  def s2f2(i: Int): Reader[Env,Int] =
    for {
      s <- Reader((_: Env)._1)
      r1 <- s.s1f1.local((_: Env)._2)
      r2 <- s.s1f2.local((_: Env)._2)
    } yield r1 + r2 + i
}

然后:

scala> object s1 extends Service1_1
defined object s1

scala> object s2 extends Service1_2
defined object s2

scala> s2.s2f2(2).run((s1,"name"-> 2)))
res0: cats.Id[Int] = 5

这与s2f2完全相同,除了s2.s2f2(2).run(s1).run(myMap)而不是s2.s2f2(2).run((s1,myMap)),甚至只是s2 .s2f2(2).run(s1,myMap)使用改编的args.

这种方法的优点在于,即使您添加图层,也可以通过本地编写单个for-comprehension中的新读者和以前的读者.

(编辑:李大同)

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

    推荐文章
      热点阅读