Last updated:
0 purchases
factory castle
IoC container for Dart inspired by Castle Windsor + Flutter MVVM framework.
IoC and DI
Setup
Creating container
Component registration
Obtain components
Lifestyles
Singleton
Transient
Names
Component overrides
Container disposal
Container hierarchy
Flutter state management and MVVM
Root widget
View
ViewModel
Service Locator
Obtaining TickerProvider
Example
Cookbook
Roadmap
Parameterized transient components creation
Register components under multiple interfaces
Mark component as default upon registration
IoC and DI #
Setup #
IoC/DI package is platform independent so can be used in both command line apps and Flutter.
Just add it to your pubspec.yaml:
dependencies:
factory_castle:
copied to clipboard
Creating container #
import 'package:factory_castle/factory_castle.dart';
final container = FactoryContainer();
copied to clipboard
Component registration #
As name suggests components are registered into container as factory deleagates. You have to manually inject dependencies into constructor (luckily, Dart will help you).
Reflection could be used to avoid manual injection but sadly dart:mirrors library is not available for Flutter. Reflection support for non-Flutter apps may be intorduced later via separate package.
Let's register MyService which takes Logger and Config objects as parameters:
container.register<MyService>((c) => MyService(c.res<Logger>(), c.res<Config>()));
copied to clipboard
Dart is good at type inference so you don't need to explicitly specify dependency types if they are the same as parameter types. You can also omit registered component type if you don't want to abstract it with any interface.
Next example does exactly the same as previous one:
container.register((c) => MyService(c.res(), c.res()));
copied to clipboard
Each factory delegate recieves shorthand wrapper for current FactoryContainer instance as a parameter so that dependencies can be injected into constructor via res<>() method.
Components are resolved lazily which makes the order of registration not important. See the full example:
container.register((c) => MyService(c.res(), c.res()));
container.register((c) => Logger());
container.register((c) => Config(String.fromEnvironment('Flavor')));
copied to clipboard
Registering components under multiple interfaces is not supported yet. The following workaround is suggested:
final logger = FileLogger();
container.register<ILogger>((c) => logger);
container.register<Logger>((c) => logger);
copied to clipboard
Obtain components #
Call FactoryContainer.resolve<>() with component type to obtain it from container.
final repo = container.resolve<UserRepository>();
copied to clipboard
Lifestyles #
Component lifecycle can be specified via optional parameter in FactoryContainer.register():
container.register((c) => CacheEntry(c.res(), c.res()), lifestyle: Lifestyle.Transient);
copied to clipboard
Currently two lifecycle options are available.
Singleton #
Component's factory delegate is called once on first resolve<>(). Same instance is returned on every subsequent call. This is default lifestyle.
Transient #
Component's factory delegate is called on every resolve<>() call. There is no way to specify dynamic parameters yet.
Names #
You can specify component name so that this exact component is resolved when needed.
container.register<ILogger>((c) => DbLogger(), name: 'DbLogger');
container.register<ILogger>((c) => FileLogger(), name: 'FileLogger');
// ...
final fileLog = container.resolve<ILogger>(name: 'FileLogger');
copied to clipboard
Component overrides #
By default every unnamed registered component overrides previous. That is not a final design and can be changed in future. For now you can register multiple unnamed components and expect to get last one on resolve<>().
container.register<ICacheFactory>((c) => DefaultCacheFactory());
container.register<ICacheFactory>((c) => MyCacheFactory());
final cacheFactory = container.resolve<ICacheFactory>(); // MyCacheFactory
copied to clipboard
This behaviour is not consistent when both named and unnamed components are registered.
Container disposal #
Container and component disposal is not yet implemented.
Container hierarchy #
Flutter state management and MVVM #
Root widget #
View #
ViewModel #
Service Locator #
Obtaining TickerProvider #
Example #
Cookbook #
Roadmap #
Planned features.
Parameterized transient components creation #
container.registerTransient((c, p) => CacheEntry(p['key'], c.res()));
// ...
final entry = container.resolve<CacheEntry>(params: { 'key': key });
copied to clipboard
Register components under multiple interfaces #
container.register<IStorage, FileStorage>((c) => FileStorage(/*...*/));
copied to clipboard
Mark component as default upon registration #
container.register((c) => FileStorage(/*...*/, asDefault: true));
copied to clipboard
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.