Bablo
Bablo

Reputation: 916

MVVM, Dependency Injection & Runtime object creation

In DI when different objects are created at runtime using runtime parameters, what is the best way of handling object creation? I have read Mark Seemann's answer regarding using abstract factories which works very well but my question involves a scenario whereby numerous abstract factories are required for creating different view models depending on which commands are invoked.

For example, for an application described as below

Repository Layer

public interface IMainRepository { }
public interface IOtherRepository { }

Service Layer

public interface IMainService { }
  public interface IOtherService { }

  public class MainService : IMainService
  {
    public MainService(IMainRepository mainRepository)
    {
      if (mainRepository == null)
      {
        throw new ArgumentNullException("IMainRepository");
      }
      _mainRepository = mainRepository;
    }

    readonly IMainRepository _mainRepository;
  }

  public class OtherService : IOtherService
  {
    public OtherService(IOtherRepository otherRepository)
    {
      if (otherRepository == null)
      {
        throw new ArgumentNullException("IOtherRepository");
      }
      _otherRepository = otherRepository;
    }

    readonly IOtherRepository _otherRepository;
  }

View Models

public class MainViewModel
  {
    public MainViewModel(IMainService mainService, IOtherViewModelFactory otherViewModelFactory)
    {
      if (mainService == null)
      {
        throw new ArgumentNullException("IMainService");
      }
      _mainService = mainService;

      if (otherViewModelFactory == null)
      {
        throw new ArgumentNullException("OtherViewModelFactory");
      }
      _otherViewModelFactory = otherViewModelFactory;

      InitializeCommonds();
    }

    readonly IMainService _mainService;
    readonly IOtherViewModelFactory _otherViewModelFactory;

    public RelayCommand<int> CreateOtherViewModelCommand { get; set; }

    void InitializeCommonds()
    {
      CreateOtherViewModelCommand = new RelayCommand<int>(CreateOtherViewModel);
    }

    void CreateOtherViewModel(int otherId)
    {
      var otherVM = _otherViewModelFactory.Create(otherId);

      //Do other fantastic stuff...
    }
  }

  public class OtherViewModel
  {
    public OtherViewModel(IOtherService otherService, int otherId)
    {
      if (otherService == null)
      {
        throw new ArgumentNullException("IOtherService");
      }
      _otherService = otherService;

      _otherId = otherId;
    }

    readonly IOtherService _otherService;
    readonly int _otherId;
  }

View Model Factory

public class OtherViewModelFactory : IOtherViewModelFactory
  {
    public OtherViewModelFactory(IOtherService otherService)
    {
      if (otherService == null)
      {
        throw new ArgumentNullException("IOtherService");
      }
      _otherService = otherService;
    }

    readonly IOtherService _otherService;

    public OtherViewModel Create(int otherId)
    {
      return new OtherViewModel(_otherService, otherId);
    }
  }

When the CreateOtherViewModelCommand member is invoked from MainViewModel, the IOtherViewModelFactory abstract factory dependency is used to create a OtherViewModel view model. This works perfectly fine when the MainViewModel gets no more complicated than this. What happens when i have numerous other commands within MainViewModel that create other view model types? As i understand it, i would need to create other abstract factories for those also but wouldn't this lead to constructor bloat since all these abstract factory dependencies are supplied via constructor injection? Imagine a case where i required ten different abstract factories for creating different types of view models! Is there a better way of implementing what i am trying to achieve? Thanks.

Upvotes: 2

Views: 313

Answers (1)

Daniel Mann
Daniel Mann

Reputation: 58980

You've reached a point where an IoC container like Ninject will be of use to you. You define how your concrete implementations map to your interfaces, and then ask the IOC container for an object. It goes ahead and constructs the object for you, with all of the appropriate implementations provided.

Upvotes: 1

Related Questions