I'm learning Rust and experimenting with TypeId. I'm looking to see if it is possible to make a simplistic IoC container with it for Dependency Injection, but I've hit a problem with generic trait implementation for a function:
use std::any::{Any, TypeId};
trait IocInjectable<T> {
fn get_injectables_list(&self) -> Vec<TypeId>;
fn inject(&mut self, injectables: Vec<&dyn Any>) -> T;
}
impl<Func, T1, T2, TRet> IocInjectable<TRet> for Func
where
Func: Fn(&T1, &T2) -> TRet + 'static,
T1: 'static, // not sure, what goes here?
T2: 'static
{
fn get_injectables_list(&self) -> Vec<TypeId> {
return vec![TypeId::of::<T1>(), TypeId::of::<T2>()];
}
fn inject(&mut self, injectables: Vec<&dyn Any>) -> TRet {
let arg1 = injectables[0].downcast_ref::<T1>().unwrap();
let arg2 = injectables[1].downcast_ref::<T2>().unwrap();
return self(arg1, arg2);
}
}
I'm getting an error:
error[E0207]: the type parameter `T1` is not constrained by the impl trait, self type, or predicates
--> src/lib.rs:9:12
|
9 | impl<Func, T1, T2, TRet> IocInjectable<TRet> for Func
| ^^ unconstrained type parameter
Is there any way to make this approach with a function generically?
Update After reviewing answers for linked questions, I was able to solve compiler errors. Mind you, this is not optimal/final/good solution, this just solves the compiler error.
use std::any::{Any, TypeId};
trait IocInjectable<TArgs> {
type TRet;
fn get_injectables_list(&self) -> Vec<TypeId>;
fn inject(&mut self, injectables: Vec<&dyn Any>) -> Self::TRet;
}
impl<Func, T1, T2, TRet1> IocInjectable<(T1, T2)> for Func
where
Func: Fn(&T1, &T2) -> TRet1 + 'static,
T1: 'static,
T2: 'static
{
type TRet = TRet1;
fn get_injectables_list(&self) -> Vec<TypeId> {
return vec![TypeId::of::<T1>(), TypeId::of::<T2>()];
}
fn inject(&mut self, injectables: Vec<&dyn Any>) -> TRet1 {
let arg1 = injectables[0].downcast_ref::<T1>().unwrap();
let arg2 = injectables[1].downcast_ref::<T2>().unwrap();
return self(arg1, arg2);
}
}