Choosing between DI (without container) and Composition

I’m working on a classes that are designed to read a defined file format; said format is comprised of 2 separate files (FileA and FileB). For ease of use, the format is referred to as the FileA format, but a valid “file” must have a FileB. The files share the same path prefix, but alter in suffix; therefore my current classes appears as:

class FileReaderA:
    def __init__(self, path: pathlib.Path):
            self.a = path.with_suffix('.fa')
            self.b = FileReaderB(path)
    # methods related to operating on FileA types

class FileReaderB:
    def __init__(self, path: pathlib.Path):
            self.b = path.with_suffix('.fa')
    # methods related to operating on FileB types 

The classes are separated since FileReaderB does not depend on FileReaderA and can be used independently to read FileB types, however a valid FileA requires its associated FileB. Therefore, composition made sense, at first. Now I’m wondering if DI is the more appropriate solution, but it requires that FileReaderB be explicitly instantiated and passed to the constructor of FileReaderA, which is less than ideal form a user standpoint with this API:

>>> frb = FileReaderB(path)
>>> fra = FileReaderA(path, frb)

Thus I am forced to abstract it by using a factory:

def reader(path: pathlib.Path):
    return FileReaderA(path, FileReaderB(path))


>>> fra = reader(path)

This seems verbose and I feel as though I’m introducing more code and layers of abstraction to achieve the same result, all around the guise for better unit testing of decoupled classes.

What is wrong with just using Composition over enforcing DI?

Go to Source
Author: pasta_sauce

Load single module based on configuration using dependency injection

I’m working on an application that will run on multiple systems and may use different modules to communicate with external systems, but on each system, only one module will be used at a time. As it should be possible to change the used module on a specific system, the same application with all modules should be deployed to all systems. For simplicity, let’s assume that there are two modules called Foo and Bar.

Both modules have their own module descriptor that registers the module components to the dependency injection container:

public class FooModule : IModule
{
    public void Configure(IServiceCollection services)
    {
        services.AddTransient<IService, FooService>();
        // Register dependencies of FooService
    }
}

I know that Autofac supports modules out of the box (even with support for configuration) and there are several libraries that add such a feature to Microsoft.Extensions.DependencyInjection, but I want to ask this question with a general look at the concept of dependency injection.

If the services of all modules should be used at the same time, I would be done. Given they implement the same service, I could inject them using IEnumerable<IService>. But in my use case, there is a component that requires a single IService and I want to select the implementation based on a configuration (e.g. from a file).

Now there are several approaches where to apply that configuration and I’m not sure which one should be preferred:

1st approach – load single assembly

I could read the configuration and then load only the external assembly that contains the IModule that should be used. This would require the introduction of some “magic” link between the configuration values and the names of the module assemblies, as the core application should not know the extension modules beforehand.

2nd approach – call single module

All the assemblies are loaded, but using a link between the configuration values and the names of the module classes (or namespaces), only the one module that should be used will be called to setup the passed IServiceCollection.

3rd approach – let the module decide

The modules decide on their own if they are configured and therefor should provide their service implementation. Instead of evaluating the configuration in the core application, the configuration gets passed to the modules:

public class FooModule : IModule
{
    public void Configure(IServiceCollection services, IConfiguration configuration)
    {
        if (configuration.GetSection("foo").Exists())
        {
            services.AddTransient<IService, FooService>();
        }
    }
}

4th approach – use some DI container feature

I know that Autofac or other DI containers support named / keyed service registrations that would basically solve this problem and therefor answer this question for me. However, I guess there is a reason why other DI containers like Microsoft.Extensions.DependencyInjection do not provide this feature.


What approach would you prefer? Is there an approach or some variation that I missed? Is there anything else I should keep in mind when designing a system in that way?

Go to Source
Author: Lukas K├Ârfer

Dependency Injection with MVVM pattern in Simple WPF Application

I’ve been trying to follow the advice in this answer

The problem is I get the error: No matching constructor found on type ‘FreecycleFrontEnd.MainWindow when the application starts up

Code below:

public partial class App : Application
    {
        private static readonly Logger log = LogManager.GetCurrentClassLogger();
        private IKernel container;


    protected override void OnStartup(StartupEventArgs e)
    {
        log.Debug("Application Starting Up");

        IocKernel.Initialize(new IocConfiguration());
        base.OnStartup(e);
       

    }

}
public partial class MainWindow : Window
{
    private IWebController _controller;
    public MainWindow(IWebController controller)
    {
        this._controller = controller;
        InitializeComponent();
        Loaded += onLoaded;
    }

 public class IocConfiguration : NinjectModule
{
    public override void Load()
    {

        Bind<IWebController>().To<WebController>().InSingletonScope();
        Bind<UserControlViewModel>().ToSelf().InTransientScope(); // Create new instance every time
    }
}
public static class IocKernel
{
    private static StandardKernel _kernel;

    public static T Get<T>()
    {
        return _kernel.Get<T>();
    }

    public static void Initialize(params INinjectModule[] modules)
    {
        if (_kernel == null)
        {
            _kernel = new StandardKernel(modules);
        }
    }
}

The code compiles, and executes up to base.OnStartup(e);
The Ninject configuration executes.

What have I missed?

Go to Source
Author: tonydev314