Scala:蛋糕模式的延迟烘焙和运行时编译
蛋糕图案的一大局限性是它是静态的。我希望能够完全独立地将可能由不同编码人员编写的特性混合在一起。然而,这些特征将而不是需要经常混合。用户将有一个初始化屏幕,在主应用程序运行之前,他们将在其中选择特征/程序集。因此,我想到了为什么不在用户选择模块中混合并编译所选特征。如果编译失败,没有问题,用户只需返回一些消息不兼容的程序集或其他任何东西。如果编译成功,那么顶层UI模块将加载新编译的类和程序集的预编译部分,并运行主应用程序。注意,在运行时初始化期间,可能只需要编译一个或两个类。所有其余的代码都可以正常编译 我对Scala还很陌生这是公认的模式吗?有什么支持吗?对于相对简单的依赖情况,必须使用Guice似乎很疯狂我可以在应用程序中轻松运行Scala编译器吗?我是否可以在内存中运行它,并从内存中使用它的输出,而无需创建不必要的文件? 注:尽管该方法看起来是动态的,但仍将保持100%的静态。Scala:蛋糕模式的延迟烘焙和运行时编译,scala,dynamic,compiler-construction,cake-pattern,Scala,Dynamic,Compiler Construction,Cake Pattern,蛋糕图案的一大局限性是它是静态的。我希望能够完全独立地将可能由不同编码人员编写的特性混合在一起。然而,这些特征将而不是需要经常混合。用户将有一个初始化屏幕,在主应用程序运行之前,他们将在其中选择特征/程序集。因此,我想到了为什么不在用户选择模块中混合并编译所选特征。如果编译失败,没有问题,用户只需返回一些消息不兼容的程序集或其他任何东西。如果编译成功,那么顶层UI模块将加载新编译的类和程序集的预编译部分,并运行主应用程序。注意,在运行时初始化期间,可能只需要编译一个或两个类。所有其余的代码都可以
微软Roslyn项目的一个驱动程序就是为C#和Visual Basic启用这种功能。但是,即使对于一个强大的微软团队来说,这似乎也是一个相当大的项目。直接从Scala内部调用编译器是可行的,但对于胆小的人来说却不行。幸运的是,Twitter上的好人已经为你自动化了这个过程。(140个字符的名人微博和一些很酷的Scala实用程序!谢谢Twitter。)您可以使用com.Twitter.utils.Eval类编译和计算Scala字符串。在您的示例中,您将执行以下操作
val eval = new Eval()
val myObj = eval[BaseClass]("new BaseClass extends " + traitNameList.mkString(" with "))
这将为你创建一个新的对象,其中包含你想要的所有特性。然后问题就出现了,这是否是一个好主意。缺点:
- 调用Scala编译器并不快
- 如果这样做足够多,就会使PermGen空间过载,因为您创建的类永远不会被垃圾收集
- 这实际上更像是一种动态语言,而不是Scala。你很可能会发现这样的设计可以发挥所有的作用,但与你的架构的其他部分有冲突(是的,这是模糊的)
val eval = new Eval()
val myObj = eval[BaseClass]("new BaseClass extends " + traitNameList.mkString(" with "))
这将为你创建一个新的对象,其中包含你想要的所有特性。然后问题就出现了,这是否是一个好主意。缺点:
- 调用Scala编译器并不快
- 如果这样做足够多,就会使PermGen空间过载,因为您创建的类永远不会被垃圾收集
- 这实际上更像是一种动态语言,而不是Scala。你很可能会发现这样的设计可以发挥所有的作用,但与你的架构的其他部分有冲突(是的,这是模糊的)