Choose dependency for injection using Kiwi in Flutter - flutter

I have the following code:
KiwiContainer()
..registerFactory((c) => GetOrderListOfItemsUseCase(
repository: c<ShopRepository>()))
The problem here is that the GetOrderListOfItemsUseCase requires an instance of IProfileRepository which the ShopProfileRepository extends from.
NOTE: IProfleRepository is extended by IUserProfileRepository and IShopProfileRepository.
UPDATE: I have the following factories:
..registerFactory<IShopRepository>((c) => c<ShopRepository>())
..registerFactory<IUserProfileRepository>((c) => c<UserProfileRepository>())
The thing is that I want to dynamically inject the proper dependency for GetUserLocationsUseCase.
..registerFactory(
(c) => GetUserLocationsUseCase(repository: c<IProfileRepository>()))
how can I inject in the code the proper subtype of IProfileRepository whether it IShopRepository or IUserProfileRepository?

If you want to dinamically inject either UserProfileRepository or ShopProfileRepository you should register the one you are going to use via its supertype.
KiwiContainer()
..registerFactory<IProfleRepository>((c) => ShopProfileRepository())
..registerFactory((c) => GetOrderListOfItemsUseCase(
repository: c<IProfleRepository>()))
And obtain it via its supertype too, like in the snippet.

Related

How to resolve dependency in dependency register time in Autofac

earlier I used Microsoft unity IOC. Unity container has RegisterType & Resolve method. So I able to resolve same interface with multiple implementation. but latest autofac (var builder = new ContainerBuilder();) builder hasn't resolve() method and we can't manually build (builder.Build();).
Anyone has any idea, how to convert below code base to autofac or how to use resolve method with dependency registration.
container.RegisterType<IQueryManager, FirstManager>(new TypedParameter(typeof(GeneralEnumerations.DatabaseType), GeneralEnumerations.DatabaseType.First));
container.RegisterType<IQueryManager, SecondManager>(new TypedParameter(typeof(GeneralEnumerations.DatabaseType), GeneralEnumerations.DatabaseType.Two));
container.RegisterType<IQueryManager, ThirdManager>(new TypedParameter(typeof(GeneralEnumerations.DatabaseType), GeneralEnumerations.DatabaseType.Three));
Func<DatabaseType, IQueryManager> priceFactory = (databaseType) => container.Resolve<IQueryManager>(databaseType.ToString());
container.RegisterInstance<IQueryManagerFactory<IQueryManager>>(new QueryManagerFactory<IQueryManager>(priceFactory));
I try this but not working. any suggestion how to solve this with"builder.RegisterInstance".
builder.Register<IQueryManagerFactory<IQueryManager>>(container => new QueryManagerFactory<IQueryManager>(databaseType =>
container.Resolve<IQueryManager>(new TypedParameter(typeof(GeneralEnumerations.DatabaseType), databaseType))
));

How can I access custom validators globally?

I created a my own validation class under /library/My/Validate/
In my form I have $this->addElementPrefixPath('My_Validate', 'My/Validate', 'validate');
I am using my validator like so:
$this->addElement('text', 'aField', array(
'validators' => array(
array('TestValidator', false, array('messages' => 'test failed')
),
));
This all works. However, I am interested in improving this in two ways.
I would like to make it so that all forms have access to my validator. Calling addElementPrefixPath() in every form doesn't seem to be a clean way of doing this.
I would like to pass in My_Validate_TestValidator instead of TestValidator so other developers know what they are working with right away.
To answer your first question, the only real easy way to do this would be to create your own instance of the form - My_Form_Abstract - which has an init() method that sets the prefix path - and then of course calls the parent init().
I'm not aware of a way to make your second method work flawlessly. You need to store a prefix in order to build the validator loader correctly. However, as an alternative, you might try creating new instances of the class using the full name, and then adding it to the element:
$element = $this->getElement('aField');
$myValidateTestValidator = new My_Validate_TestValidator();
$element->addValidator($myValidateTestValidator);

Make use of AllTypes.FromAssemblyContaining() / UsingFactoryMethod()

I am registering many repositories which are located in the same assembly by using the following code:
IoCContainer.Register(AllTypes.FromAssemblyContaining<RepositoryOne>).BasedOn(typeof(IRepository<>)).WithService.AllInterfaces().Configure(c => c.LifeStyle.Singleton));
Because I want to have influence on the creation of these repositories, I am trying to use UsingFactoryMethod() with it. Using this method is simple when I register every repository separately like
IoCContainer.Register(Component.For<IRepositoryOne>().ImplementedBy<RepositoryOne>().LifeStyle.Singleton.UsingFactoryMethod(() => Factory.New<RepositoryOne>()));
...
IoCContainer.Register(Component.For<IRepositoryN>().ImplementedBy<RepositoryN>().LifeStyle.Singleton.UsingFactoryMethod(() => Factory.New<RepositoryN>()));
But how can I use UsingFactoryMethod() together with the code from the first example?
TIA
You have to use a bit of reflection to use it, since you don't have the exact type of the object you'd be resolving.
var factoryMethod = typeof(Factory).GetMethod("New", BindingFlags.Static|BindingFlags.Public);
container.Register(
AllTypes.FromAssemblyContaining<RepositoryOne>)
.BasedOn(typeof(IRepository<>))
.WithService.AllInterfaces()
.Configure(x => x.UsingFactoryMethod((k, c) => factoryMethod.MakeGenericMethod(c.RequestedType).Invoke(null, null)));

Autofac: resolving different params to object using DependencyResolver

I am building an MVC application and have the need to send a different cachecontext (wraps info on which cache to use) into my repositories using the DependencyResolver. There are 10 different types of cachecontexts that can be passed in. At the moment, I am using 10 different registrations for 10 different types of interfaces (ICacheContexts). This works but does not seem like the correct way of handling this circumstance. Is there a way to create a factory that knows the object type it is being passed to so I can just determine the correct CacheContext to return and thus only have one registration to maintain?
Current code:
builder.Register(c => new CacheContext(AppConfig.AppBucketName, AppConfig.AppBucketpassword))
.As<ICacheContextForApps>();
builder.Register(c => new CacheContext(AppConfig.AcctBucketName, AppConfig.AcctBucketpassword))
.As<ICacheContextForAccounts>();
etc..
You need to do this from the repository side - for each repository, configure its parameters to resolve the right cache context. E.g. (paraphrasing)
builder.Register(c => new CacheContext(...for appls...))
.Named<ICacheContext>("apps");
builder.RegisterType<AppsRepository>()
.WithParameter((pi, c) => pi.ParameterType == typeof(ICacheContext),
(pi, c) => c.ResolveNamed<ICacheContext>("apps"));
Hope this gets you on the right track.

having problems with Zend framework validators

I'm having problem with custom builded validator that does not returns any error. I copied a file NotEmpty.php form folder library/Zend/Validate, rename class Zend_Validate_NotEmpty to My_Validate_EmailConfirmation and put it into folder My/Validate.
If I call this class like
->setRequired(true)->addValidator('NotEmpty',true,array('messages' => array('isEmpty' => "bla")));
I get the correct error, but if i call it like
->setRequired(true)->addValidator('EmailConfirmation',true,array('mess ages' => array('isEmpty' => "bla")))->addPrefixPath('My_Validate','My/Validate/','validate');
i get nothing...
What am i doing wrong?
Thanks is advanced for your answers...
Have you tried to set in your bootstrap file your new namespace?
Zend_Loader_Autoloader::getInstance()->registerNamespace('My');
Also, why not you just extends the NotEmpty validator instead of duplicate the class?