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

How to provide factoryParam to nested classes? #471

Open
ChaserVasya opened this issue Jun 11, 2024 · 4 comments
Open

How to provide factoryParam to nested classes? #471

ChaserVasya opened this issue Jun 11, 2024 · 4 comments

Comments

@ChaserVasya
Copy link

ChaserVasya commented Jun 11, 2024

I have next structure:

Bloc(
    Interactor(
       String locationId
     )
)

I want to call something like getIt<Bloc>(param1: locationId), where locationId will be provided to Interactor. How to do this with Dependency Injection principe?

@migalv
Copy link

migalv commented Oct 5, 2024

I have a similar issue.

I have a logger that I pass to a lot of my classes. But this logger is registered as a factory, so each class has it's own logger. This factory has a String parameter to identify the logger for each class.

But when a class has a dependency to the logger, I cannot pass this argument in the getIt.

@named
@Injectable(as: Interface)
class MyClass implements Interface {
  MyClass(this.logger);

  final Logger logger;
}

@injectable
class Logger {
  const Logger(@factoryParam this.context);

  final String context;
}

This generates:

  gh.factoryParam<_i1055.Logger, String, dynamic>(
      (
        context,
        _,
      ) => _i629.Logger(context),
    );
    gh.factory<_i630.Interface>(
      () => _i641.MyClass(
        logger: gh<_i1055.Logger>(),
      ),
      instanceName: 'MyClass',
    );

@ChaserVasya
Copy link
Author

ChaserVasya commented Oct 5, 2024

@migalv

I created a solution that looks like this

 Bloc(this.interactor);

 @factoryMethod
  factory Bloc.di(
     @factoryParam Id locationId,
     ) =>  Bloc(Interactor(locationId)),
 );

@migalv
Copy link

migalv commented Oct 5, 2024

Oh yeah nice approach @ChaserVasya. Another solution I found is:

You can create a module for that Bloc and pass the Interactor that you want there:

@module
abstract class BlocProvider {
  @injectable
  Bloc getBloc(@factoryParam Id locationId) => Bloc(getIt<Interactor>(param1: locationId));
}

Then you can use it as you would normally:

final bloc = getIt<Bloc>();

@ChaserVasya
Copy link
Author

ChaserVasya commented Oct 6, 2024

@migalv

  1. Your example doesn't guarantees that Interactor registered in getIt before Bloc. Auto-ordering is important feature of injectable.

Solution: Create Interactor by hand, like in my example

  1. IMHO , During the development process, we often change constructors. In order not to forget to change param1, param2, it is more convenient to keep them nearby, as in my example

  2. I often create strong-typing constructors:

 Bloc.def(this.interactor);

 @factoryMethod
  factory Bloc.di(
     @factoryParam Id locationId,
     ) =>  Bloc(Interactor(locationId)),
 );

  factory Bloc(Id locationId) =>
      getIt<Bloc>(param1: locationId);

These are not strict rules. This is just my experience

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

2 participants