Dependency Injections and Factories

What is a decent way to handle conditional windings with a DI approach. A script is a loader object that is entered into an entry, depending on the settings of that entry. I originally introduced the IoC container in the factory and used it for resolution based on naming conventions. However, I really would like to keep the factory clean in the container.

factory is introduced into a class that will load all settings from the database, and then use factory to create a set of records. Settings determine which bootloader will be used inside this record.

Edit: change the code to better highlight the actual issue. The problem is that multiple database managers must be supported at the same time, if it is not, then it will be simple. The type of database manager is determined by the record parameters stored for a particular record.

public class Entry : IEntry { private ISomething loader; public Entry(ISomething something) { this.loader = something; } } public class EntryFactory : IEntryFactory { IEntry BuildEntry(IEntrySetting setting) { //Use setting object to determine which database manager will be used } } public class EntryManager { public EntryManager(IEntryFactory entryFactory) { var entrySettings = this.settings.Load(); foreach(var setting in entrySettings) { this.entries.Add(entryFactory.BuildEntry(setting)); } } } 

I believed that the register of subfiles is registered in the main factory and resolves them that way, but I don't know if there is a better approach.

+6
source share
2 answers

What I usually do is create a wrapper for my DI container ... Something like IDependencyResolver ... And introduce it to my factories. You can then implement an implementation, such as StructureMapDependencyResolver, that does the lifting. I like it better than injecting the container itself, because it allows me to change DI containers immediately (almost). At least my factories should not change.

 public interface IDependencyResolver { T Resolve<T>(); } public class UnityDependencyResolver : IDependencyResolver { private readonly IUnityContainer _container; public UnityDependencyResolver(IUnityContainer container) { _container = container; } public T Resolve<T>() { return _container.Resolve<T>(); } } 

This approach is so flexible that you can implement your own Resendvers Dependency Resolvers and enter them manually.

 public class ManualDependencyResolver : IDependencyResolver { public T Resolve<T>() { if (typeof(T)==typeof(ITransactionRepository)) { return new CheckTransactionRespostory(new DataContext()); } throw new Exception("No dependencies were found for the given type."); } } 
+1
source

It depends on what your DI infrastructure allows, and you did not specify it. Using Autofac registration-based delegation, I came up with the following solutions. Note that ILoaderFactory and IEntryFactory were replaced by simple Func<> factories in both cases.

Solution 1 using two factories:

 public class EntryManager { public EntryManager(Func<ILoader, IEntry> entryFactory, Func<Settings, ILoader> loaderFactory) { var entrySettings = this.settings.Load(); foreach(var setting in entrySettings) { this.entries.Add(entryFactory(loaderFactory(setting))); } } } private static ILoader SelectLoader(IEntrySetting settings) { // your custom loader selection logic } var builder = new ContainerBuilder(); builder.RegisterType<EntryManager>(); builder.RegisterType<Entry>().As<IEntry>(); builder.Register((c, p) => SelectLoader(p.TypedAs<IEntrySetting>())); IContainer container = builder.Build(); container.Resolve<EntryManager>(); 

Solution 2 using only one factory:

 public class EntryManager { public EntryManager(Func<IEntrySetting, IEntry> entryFactory) { var entrySettings = this.settings.Load(); foreach(var setting in entrySettings) { this.entries.Add(entryFactory(setting)); } } } private static ILoader SelectLoader(IEntrySetting settings) { // your custom loader selection logic } var builder = new ContainerBuilder(); builder.RegisterType<EntryManager>(); builder.Register((c, p) => new Entry(SelectLoader(p.TypedAs<IEntrySetting>()))).As<IEntry>(); IContainer container = builder.Build(); container.Resolve<EntryManager>(); 
0
source

Source: https://habr.com/ru/post/893714/


All Articles