-
-
Notifications
You must be signed in to change notification settings - Fork 153
Ready handler for synchronous creations of instances #115
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
Comments
you only need such a system if async singletons are involved because Dart is single threaded. you can use registerSingletonWidthDependency if you have a sync singleton that depends on one or more async singletons. |
Do you mean something like this? sl.registerLazySingleton<ClassA>(() => ClassA());
sl.registerSingletonWithDependencies<ClassB>(
() {
var b = ClassB();
b.doSomeStuffWithA(sl<ClassA>());
return b;
},
dependsOn: [ClassA]); I hadn't thought of using registerSingletonWithDependencies since its not lazy, but I now assume that depending on a lazily created instance makes it lazy, do you confirm? |
Nope, you only can use async singletons or other In the scenario in your example you have to do nothing. just declare both as Lazy and you are fine |
OK, but then how do I trigger code upon creation of ClassA without introducing dependencies inside it? One option would be to trigger it from inside the ClassA constructor, using a callback: ClassA {
ClassA({Function onCreated}) {
Function.apply(onCreated, [this]);
}
}
sl.registerLazySingleton<ClassA>(() => ClassA(
onCreated: (a) {
sl<ClassB>().doSomeStuffWithA(a):
}));
sl.registerLazySingleton<ClassB>(() => ClassB()); But I'd rather avoid it because it looks weird and clutters ClassA. And since GetIt handles the creation of instance I though it would be natural for it to notify when instances are created. |
Why is it important to know when the instance of A is created? It happens to moment the first tries to access it. I'm just trying to understand your application to come up with a good idea. You are the first asking for something like that. |
Because I need to run some code at that moment: as soon as the class is created I want to register it as a listener to another one. It is not possible before because the instance doesn't exist (since it's created lazily), and it must be done as soon as the instance exists.
I am doing all the registering in a single container file and almost never use GetIt elsewhere (I use it in the views to inject view models). All the classes get their dependencies injected in this container file. I want to add bindings between classes at the moment I define their creation because it would be simpler to do it there. |
Hmm, I wouldn't do it that way, but just in case. Also lazy registrations only make sense for objects that take time to construct or are otherwise expensive. |
Yes, doing the needed stuff inside the constructor of A seems the way to go. But I don't want all my classes to have a dependency to GetIt and in general I prefer to inject instances through constructors. So I can adapt the classes in order to make the dependency added to A acceptable : define an interface for class B, make A depend on this interface and inject the implementation in the constructor of A. But I encounter the following problem: class B actually implements 2 interfaces and I would like to get the same instance when asking any of these 2 interfaces: abstract class Contract1 {
void method1();
}
abstract class Contract2 {
void method2();
}
class B implements Contract1, Contract2 {
@override
void method1() => print('method1');
@override
void method2() => print('method2');
}
// first attempt -------------
// this registers a different instance of B for Contract2:
sl.registerLazySingleton<Contract1>(() => B());
sl.registerLazySingleton<Contract2>(() => B());
assert(sl<Contract1>().hashCode == sl<Contract2>().hashCode, 'different'); // --> different
// second attempt -------------
// this works but is akward isn't it?
// It only works because we know that the implementation of Contract1 is also a Contract2.
sl.registerLazySingleton<Contract2>(() => sl<Contract1>() as Contract2);
assert(sl<Contract1>().hashCode != sl<Contract2>().hashCode, 'same'); // --> same What do you think about
Since I am doing all the registering at startup I think the time to call all these constructors will add up and increase the app starting time. So I prefer to only create what is needed and defer the rest to later. |
Unfortunately automatic injection through the constructor isn't possible without code generation and I'm not a fan of it because its to much magic going on. I always use interfaces as the type to register a singleton so you are free to switch implementations any time. If you decide to go with a service locator I don't see anything bad using it inside all classes where needed. BTW have you already heard that there is now a get_it_mixin and a get_it_hooks? |
Uh oh!
There was an error while loading. Please reload this page.
I am using GetIt in an injection container and I would like to trigger some code when a singleton is created lazily and synchronously. The API could be something like this:
Which would do this: when the instance of A is created, the callback creates an instance of B (
sl<ClassB>()
) that do some stuff with the A instance (for example adding it as a listener). Here the classes don't need to perform async tasks when created, they just need to be created only when needed, be ignorant of each other and triggeronReady
when created.Is there already a way to do this? As far as I understand the signalsReady/isReady/dependsOn/etc. stuff is for async singletons and factories.
The text was updated successfully, but these errors were encountered: