Name |
|
||||||
---|---|---|---|---|---|---|---|
Backends | JVM JavaScript | ||||||
Maven coordinates | |||||||
Compatible Ceylon release |
JVM: 1.2.x, 1.3.x (latest) JavaScript: 1.2.0 (outdated) |
||||||
Published | Dec 15, 2015 | ||||||
Stats |
Downloads (JVM): 210 Downloads (JS): 69 Source downloads: 295 |
||||||
Authors |
Jonas Grönberg |
||||||
Description |
bushelBushel is a Dependency Injection (DI) framework, written especially for the Ceylon programming language. Bushel features the things you normally expect from modern Java DI frameworks, like
The goal is to provide familiar and proven Java DI concepts in a more ceylonic way, primarily utilizing the expressive type system of Ceylon. introConsider the Bushel Container container = scanAnnotated<ComponentAnnotation> { `package se.westshed.pump` }; Then, consider the following components residing in the package, handed to the container: component Heater heater() => ElectricHeater(); component class Thermosiphon(Heater heater) satisfies Pump { shared actual void pump() { if (heater.hot) { print("=> => pumping => =>"); } } } Doing Thermosiphon t = container.get<Thermosiphon>(); will get you … a thermosiphon. Normally, you would ask the container for a pump like this: Pump pump = container.get<Pump>(); assert(is Thermosiphon pump); If you suspect that there might be no Pump implementation in the container, then you can write: Pump? p = container.get<Pump?>(); This also opens up for components having optional dependencies: class Widget(Pump? pump) {} qualifiersConsider that we have two different implementations of the same Heater interface in the container. component Heater heater1() => ElectricHeater(); component Heater heater2() => ManualHeater(); component class Thermosiphon(Heater heater) satisfies Pump { shared actual void pump() { if (heater.hot) { print("=> => pumping => =>"); } } } In this case, it is impossible for the Bushel container to know, which Heater implementation to use when wiring the heater dependency for the Thermosiphon component. Simply put, we have to provide a hint to the container. Assume that we want to use the ElectricHeater. The most type safe way of doing this, is using a Qualifier annotation, provided by the Bushel framework. "The electric heater qualifier" shared annotation ElectricHeaterQualifier electricHeater() => ElectricHeaterQualifier(); "The qualifier class for electricHeater." shared final sealed annotation class ElectricHeaterQualifier() satisfies Qualifier<ElectricHeaterQualifier,Heater> { equals(Object that) => that is ElectricHeaterQualifier; hash => 0; } You can now annotate the ElectricHeater component as well as the heater parameter to be wired, like this to let the Bushel container know about the association: component electricHeater shared Heater heater1() => ElectricHeater(); component Heater heater2() => ManualHeater(); component class Thermosiphon(shared electricHeater Heater heater) satisfies Pump { //... } This now holds true: Thermosiphon t = container.get<Thermosiphon>(); assert(is ElectricHeater heater = t.heater); The Ceylon type system will ensure that you never accidentally annotate another type but a Heater implementation, because that will give you a compile error. The Ceylon type system will even let you do this, inferring the right type on the fly. Heater heater = container.getQualified(electricHeater()); |
||||||
Dependencies |
|
||||||
Usage |
import se.westshed.bushel "0.4.0"; $ ceylon run se.westshed.bushel/0.4.0 <property name="ceylon.home" value="…"/> <property name="ceylon.ant.lib" value="${ceylon.home}/lib/ceylon-ant.jar"/> <path id="ant-tasks"> <pathelement path="${ceylon.ant.lib}"/> </path> <typedef resource="com/redhat/ceylon/ant/antlib.xml" classpathref="ant-tasks"/> <target name="run"> <ceylon-run module="se.westshed.bushel/0.4.0"/> </target> |
||||||
Module links |
Members Imported By Browse Download .car Download .js Download source archive Download module documentation View API documentation |