Closed dalewking closed 1 year ago
This is really becoming a problem for me in my project right now
@dalewking my apologies but, my father is a having some health problems these days and I'm no shape to code. I guess you could use a module for the time being
//Injectable will handle foo's deps if it's an
//abstract getter/method
@injectable
Foo foo();
@injectable
Bar bar() => Bar(foo);
No rush you do what you need to do. If I have some time I will look into it.
I have another work around. I created a type called Supplier:
abstract class Supplier<T> {
T call<T>();
}
In the same area of code that I call $initGetIt I have this:
@Injectable(as: Supplier)
class GetItSupplier implements Supplier {
@override
T call<T>() => GetIt.I();
}
So then Bar is declared like this:
class Bar {
final Supplier<Foo> fooBuilder;
Bar(this.fooBuilder);
Foo get foo => fooBuilder();
}
This works, but I get no build time type checking. If I did not have a binding for Foo in GetIt this would fail at run-time so less than ideal but I do not need to do all the boilerplate.
OK, ignore what I said about my Supplier workaround as that did not work.
I do now see how to detect if a type is a function. At this point in the code type is FunctionType
will tell you that it is a function type. The exception on name is coming from the call to type.element.name
in the next line because element is null for FunctionType.
It will take more time to unravel the code to see how to use that.
Did you solve this @dalewking? Have a similar situation here
Think I just changed the design and dealt with the lack of encapsulation by referencing the GetIt instance. It was a proof of concept project that I haven't touched in 2 months, so don't really remember the details any more.
Needs this too. Use case:
We have some async deps in graph but want the whole graph to be sync. It is crucial for our architecture - some sort of 'controlled async' so we can show nice animations etc when, for example, our database is decrypted or initialized. So we incapsulate some async deps in few places in sync graph. For example:
@module
abstract class ProfileRepoModule {
@singleton
ProfileRepository provideProfileRepo(
Future<ProfileDAO> dao,
RestClient restClient,
) => ProfileRepositoryImpl(dao, restClient);
}
This way we await DAO initialization in ProfileRepositoryImpl
and not turn whole graph into async. Currently we use ugly workaround for this:
@module
abstract class ProfileRepoModule {
@singleton
ProfileRepository provideProfileRepo(
ServiceLocator sl,
RestClient restClient,
) => ProfileRepositoryImpl(sl.getAsync<ProfileDAO>(), restClient);
}
Where is ServiceLocator
our own wrapper around GetIt.
It feels very natural to inject sync or async factories as dependencies. For async it can be implemented very straightforward without any new interface - just for any binging of T
support injection of Future<T>
. For sync case I do not what is optimal factory interface.
I think that I can provide a PR for async case at least. @Milad-Akarie do you interested in such functionality/PR?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions
So the injection is all about injection of an instance of a class. What I am looking for is an easy way to inject a function that creates the instance without referencing the getIt instance itself.
Say I have some class Foo:
And I have another type Bar that has its constructor parameter a function that returns Foo
Trying to figure out how to make Bar injectable. I can tell you that just adding
@injectable
to Bar gives you this error:So one thought was doing this in a module:
But that doesn't work:
But even if it did work, it is cumbersome if you want to do it a lot and it destroys encapsulation as it requires me to reference the GetIt instance directly in the module.
One way to do it is if I move all of the specification to a module:
But if Foo had dependencies I would be forced to deal with that boilerplate in the module instead of letting Injectable deal with it.
If you look at the documentation for Dagger here you can see that they handle this with Lazy and Provider types. They use a specific type for it since functions aren't first class citizens in Java, but you could do it just by looking for function returning an injectable type.
So it would be nice if you could recognize that a dependency is a Function with no parameters returning an Injectable type and create the function automatically.