Crate metafactory [stability]
[-]
[+]
[src]
MetaFactory
can be used to construct value creation chains from
closures or other sources that produce values.
Let's look at really small example first:
use metafactory::{ metafactory, argless_as_factory, AsFactoryExt }; fn main() { let meta_sum = metafactory( |a: int, b: int| a + b ); let sum_factory = meta_sum.new(vec![ argless_as_factory(5i), argless_as_factory(6i), ]).ok().unwrap(); let getter = sum_factory.as_factory_of::<int>().unwrap(); assert_eq!(getter.take(), 11); }
What is going on? Well, first we use metafactory
generic function to
convert arbitrary closure to MetaFactory
object meta_sum
.
It has a method new
, which is used above to return a real
concrete factory sum_factory
. As argument, it takes other factories.
The method argless_as_factory()
returns factories for clonable values
5i
and 6i
.
So, metafactories can be created from different sources: clonable
objects or closures. In this case 5i
is a clonable object.
Returned sum_factory
has a Box<Any>
type, and can be downcasted to
a Factory
of appropriate type with as_factory_of
method.
Then you can call take()
on this factory getter
to invoke your closure
and return a new value.
Note a lot of unwrap
calls. All the potential argument or type
mismatches produce correct errors that can be dealt with.
Now, the example above might seem a bit involved, but consider what it allows us to do: provided argument counts and types match, we can connect any chain of factories together, at runtime.
Let's expand example to add a new factory that uses sum_factory
as an
argument, and creates our own struct:
use metafactory::{ metafactory, argless_as_factory, AsFactoryExt }; /// Our own struct. struct Foo { value: int, } fn main() { // initialization let meta_sum = metafactory( |a: int, b: int| a + b ); let meta_foo = metafactory( |sum: int| Foo { value: sum } ); // plugging in let foo_factory = meta_foo.new(vec![ meta_sum.new(vec![ argless_as_factory(5i), argless_as_factory(6i), ]).ok().unwrap() ]).ok().unwrap(); // using let getter = foo_factory.as_factory_of::<Foo>().unwrap(); assert_eq!(getter.take().value, 11); }
So, the intention of this library is to have a mechanism to separate 3 things: creating the values, plugging-in the factories values, and using them.
Created metafactories can also be used to inspect closure argument types. It is also possible to clone the created factory: in such case, all the call tree is also cloned internally. This makes it possible to pass a copy of a factory to a task.
Factories intentionally do not produce any kind of singletons or references, only new values. You can also look at them as configurable stream of values.
If this library looks a bit lower-level, it is because it is intended as such: more convenient wrappers like dependency injection or plugin architecture can be implemented on top of this.
Finally, a more complete example of available functionality:
use metafactory::{ metafactory, AsFactoryExt }; fn main() { // build argument-factory from cloneable source. let meta_arg1 = metafactory(5i); // build argument-factory from lambda. let meta_arg2 = metafactory(|| 14i32); // build a factory that uses other factories create added numbers. let meta_adder = metafactory(|a1: int, a2: i32| a1 + a2 as int); // it knows the cloneable source returns int assert!(meta_arg1.get_type().is::<int>()); // it knows the lambda source returns i32 assert!(meta_arg2.get_type().is::<i32>()); // it knows the lambda with 2 args returns int assert!(meta_adder.get_type().is::<int>()); // create a factory for adder, pass other 2 factories as arguments let boxany = meta_adder.new(vec![ meta_arg1.new(Vec::new()).ok().unwrap(), meta_arg2.new(Vec::new()).ok().unwrap(), ]).ok().unwrap(); // conveniently downcast factory to callable instance let factory = boxany.as_factory_of::<int>().unwrap(); // value should be the sum. assert_eq!(19, factory.take()); // factory can be cloned let factory2 = factory.clone(); // both clones invoke the same construction path and return the same value assert_eq!(factory.take(), factory2.take()); }
Modules
aggregate | Implements a factory that aggregates the results of other factories of the same type. |
error | Closure argument error types. |
Structs
Factory | A factory proxy. |
Traits
AsFactoryExt | Downcast value to |
Getter | Gettable value trait. |
MetaFactory | Implements reflection and initiation of any abstract object constructor. |
ToMetaFactory | Trait for values convertable to |
Functions
argless_as_factory | Create a new |
metafactory | Create a new |