Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Roadmap #1

Open
2 of 3 tasks
Nercury opened this issue Oct 23, 2015 · 0 comments
Open
2 of 3 tasks

Roadmap #1

Nercury opened this issue Oct 23, 2015 · 0 comments

Comments

@Nercury
Copy link
Owner

Nercury commented Oct 23, 2015

Basic TODO list.

  • Replace current DI mechanism with much simpler Ownership-based dependency injection: Proof of concept here:
use std::any::{ Any, TypeId };
use std::collections::HashMap;
use std::collections::hash_map::Entry;

#[derive(Debug)]
pub struct Scope<T> {
    pub obj: T,
    childs: Vec<Box<Any>>,
}

pub trait WithAll<T> {
    fn with_all(self, deps: &Dependencies) -> Scope<T>;
}

impl<T: Any> WithAll<T> for T {
    fn with_all(self, deps: &Dependencies) -> Scope<T> {
        deps.create_dependencies(self)
    }
}

pub struct Dependencies {
    constructors: HashMap<TypeId, Vec<Box<Fn(&Dependencies, &Any) -> Box<Any>>>>,
}

impl Dependencies {
    pub fn new() -> Dependencies {
        Dependencies {
            constructors: HashMap::new()
        }
    }

    pub fn create_dependencies<P: Any>(&self, obj: P) -> Scope<P> {
        match self.constructors.get(&TypeId::of::<P>()) {
            Some(list) => {
                let dependencies: Vec<_> = list.iter()
                    .map(|any_constructor| any_constructor(&self, &obj))
                    .collect();

                Scope { obj: obj, childs: dependencies }
            },
            None => Scope { obj: obj, childs: vec![] },
        }
    }

    pub fn on_one<P, C, F>(&mut self, constructor: F)
        where
            P: 'static + Any, C: 'static + Any,
            F: for<'r> Fn(&'r Dependencies, &P) -> C + 'static
    {
        self.upsert(TypeId::of::<P>(), any_constructor(constructor));
    }

    fn upsert(
        &mut self,
        type_id: TypeId,
        any_constructor: Box<Fn(&Dependencies, &Any) -> Box<Any>>
    ) {
        match self.constructors.entry(type_id) {
            Entry::Occupied(mut list) => {
                list.get_mut().push(any_constructor);
            },
            Entry::Vacant(e) => {
                e.insert(vec![any_constructor]);
            },
        };
    }

}

fn any_constructor<P, C, F>(constructor: F) -> Box<Fn(&Dependencies, &Any) -> Box<Any>>
    where F: for<'r> Fn(&'r Dependencies, &P) -> C + 'static, P: 'static + Any, C: 'static + Any
{
    Box::new(move |deps: &Dependencies, parent: &Any| -> Box<Any> {
        let concrete_parent = parent.downcast_ref::<P>().unwrap();
        let child = constructor(deps, concrete_parent);
        Box::new(child)
    })
}

fn main() {
    let mut deps = Dependencies::new();

    deps.on_one(|_, parent: &i32| println!("hello {:?}", parent));
    deps.on_one(|deps, _: &i32| true.with_all(deps));
    deps.on_one(|deps, _: &i32| false.with_all(deps));
    deps.on_one(|_, parent: &bool| println!("bool {:?}!", parent));

    5.with_all(&deps);
}
  • Find simple way to connect dependency injection scope lifetimes;
  • Test usability in some simple real project and fix any design issues.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant