hampusmat / syrette Goto Github PK
View Code? Open in Web Editor NEWThe convenient dependency injection library for Rust. Mirror of https://git.hampusmat.com/syrette
Home Page: https://git.hampusmat.com/syrette
License: Apache License 2.0
The convenient dependency injection library for Rust. Mirror of https://git.hampusmat.com/syrette
Home Page: https://git.hampusmat.com/syrette
License: Apache License 2.0
To be able to pass the DI container as a reference in the future
It's a big hassle that a factory function have to be nested inside of another function when passed to the to_*factory
binding builder functions. Instead of the wrapping function taking a DI container reference, the factory function can take a DI container reference and can be curried before it is given to the user.
The traits IDIContainer
and IAsyncDIContainer
should be removed. They were created so that DIContainer
and AsyncDIContainer
can be mocked but it's much more ergonomic to just replace the whole struct. I don't know why i didn't do it that way.
This would make a type only be resolved if certain properties has specific values. Like naming it, but with arbitrary stuff.
Types could maybe a problem.
Hi! I'm loving this crate so far, so thank you for all your hard work. There's one thing which it seems to be missing to fit my use case, though:
It would be nice to be able to bind a type to an existing singleton, like so:
let my_singleton = MySingleton::new();
my_singleton.configure(/*args*/);
my_singleton.do_something_else();
di_container.bind::<MySingleton>::().to_singleton(my_singleton);
// And now we can use the specific `my_singleton` instance when resolving dependencies with the container.
Otherwise, we either have to use the factory
feature, which forces rust nightly, or depend solely on the dependency's new
function, which would make it quite challenging to configure the service based on external information.
There's a tentative PoC here: https://github.com/TechnoPorg/Syrette/tree/explicit-singleton-binding/. But I'm not especially familiar with Syrette, so I'm sure there's much there that I left out. For one thing, the injectable
derive macro still requires a new
constructor on my branch, even though it technically isn't needed.
Thanks!
The need to explicitly make injectables async compatible should be removed.
This would be simple if not for the fact that having the async
crate feature enable this by default would make it have a non-additive change. More about that here.
An alternative approach to this would be to only implement AsyncInjectable
when the type, dependencies and interface are Send + Sync + 'static
. This however is not possible (as far as i know) as long as trivial constraints is not stabilized. And even if it becomes stabilized, using it would break the 1.62.1 MSRV.
More research needs to be done about this
And possibly rename it too
Having a test return a Result
makes it a major pain the butt to find out were Err
s occur. No line number is printed as it is when unwrap
or expect
is used.
The Injectable
and AsyncInjectable
traits can be implemented for all types which implement the Default
trait.
This could look something like this:
impl<T: Default, DIContainerT> Injectable<DIContainerT> for T
{
fn resolve(
_: &DIContainerT,
_: DependencyHistory,
) -> Result<TransientPtr<Self>, InjectableError>
{
Ok(TransientPtr::new(Self::default()))
}
}
Currently, constructors are expected to be functions called "new".
A flag could be added to the injectable
macro that overrides this.
It would look like this
#[injectable(IFoo, constructor = create)]
impl Foo
{
fn create(bar: TransientPtr<dyn IBar>) -> Self
{
Self { bar }
}
}
Support for stack allocation of Injectable
s could probably be implemented.
Stack allocation is to be possible if the interface is a concrete type.
This will require
get
to be able to return either a heap allocated value (like Box) or a stack allocated value.resolve
method of Injectable
s to figure out whether dependencies should be used as heap or stack valuesSingletons with a concrete type interface does not work with the async DI container.
File to reproduce:
Partially originally posted by @dotai2012 in #1 (comment)
Currently, error handling in macros is basically just the use of .unwrap()
.
This has worked fine but produces unclear error messages. So it should be improved on.
One alternative is using the proc-macro-error crate.
The expansion of the injectable
attribute currently unwraps the Result
of retrieving the correct pointer type from SomePtr
macros/src/injectable/implementation.rs:283
Ok(quote! {
#do_method_call.map_err(|err| #resolve_failed_error {
reason: Box::new(err),
affected: self_type_name
})?.#to_ptr().unwrap()
})
I have no idea why i made it this way.
Replace it with the ?
operator.
The IFactory
trait is completely useless. AnyFactory
can just be downcasted to CastableFactory
. This would completely remove the need for the factory
attribute macro.
Add support for async constructors when the async
crate feature is enabled.
It would be splendid if the dependency on Linkme was gotten rid of. This would make Syrette more portable.
However, more investigating needs to be made in order to know if this is even feasible.
For example in src/di_container/asynchronous/binding/scope_configurator.rs
/// Scope configurator for a binding for type 'Interface' inside a [`IAsyncDIContainer`].
' is used when ` should be used.
This is a problem in both the async & blocking binding configurators.
This would be a great feature. It's complicated however.
I don't know why i didn't make it thread-safe in the first place
Version: 0.4.1
Problem:
Error: BindingResolveFailed { reason: ResolveFailed { reason: BindingResolveFailed { reason: ResolveFailed { reason: BindingResolveFailed { reason: DetectedCircular { dependency_history: DependencyHistory { inner: ["creditor::Foo", "creditor::Bar", "creditor::Foo"] } }, interface: "creditor::Foo" }, affected: "creditor::Bar" }, interface: "creditor::Bar" }, affected: "creditor::Foo" }, interface: "creditor::Foo" }
How to reproduce: This is the code I copied exactly from the example (https://git.hampusmat.com/syrette/tree/examples/prevent-circular)
#![deny(clippy::all)]
#![deny(clippy::pedantic)]
#![allow(clippy::disallowed_names)]
use std::error::Error;
use syrette::di_container::blocking::prelude::*;
use syrette::injectable;
use syrette::ptr::TransientPtr;
struct Foo
{
bar: TransientPtr<Bar>,
}
#[injectable]
impl Foo
{
fn new(bar: TransientPtr<Bar>) -> Self
{
Self { bar }
}
}
struct Bar
{
foo: TransientPtr<Foo>,
}
#[injectable]
impl Bar
{
fn new(foo: TransientPtr<Foo>) -> Self
{
Self { foo }
}
}
fn main() -> Result<(), anyhow::Error>
{
let mut di_container = DIContainer::new();
di_container.bind::<Foo>().to::<Foo>()?;
di_container.bind::<Bar>().to::<Bar>()?;
let foo = di_container.get::<Foo>()?.transient()?;
Ok(())
}
The methods new
, push
and contains
of DependencyHistory
should be exposed to the public API. I don't know why i didn't do it that way to begin with
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.