Sid Go
Sid Go

Reputation: 2141

Resolve an object from Windsor container that requires a data model dependency

I have an AccountViewModel object which requires two arguments in its constructor: a DataStore object registered in the WindsorContainer, and an Account data model object.

Now, when the user selects an account in a list of accounts, I need to resolve an AccountViewModel object from the container using the selected account.

But the problem is the account is not registered in the container, and when I register it on the SelectionChanged event, I ran into a duplicate registration error.

I also investigated the various life cycles for each dependency but I still can't figure out a solution (I'm obviously a beginner in using IoC frameworks since I prefer my own factory class).

Upvotes: 0

Views: 181

Answers (2)

Mark Seemann
Mark Seemann

Reputation: 233150

Keep AccountViewModel as is, but use a factory for dependency injection:

public interface IAccountViewModelFactory
{
    AccountViewModel Create(AccountModel model);
}

You can then implement (and register with your DI Container) the factory like this:

public class AccountViewModelFactory : IAccountViewModelFactory
{
    public AccountViewModelFactory(IAccountService accountService)
    {
        AccountService = accountService;
    }

    public IAccountService AccountService { get; }

    public AccountViewModel Create(AccountModel model)
    {
        return new AccountViewModel(AccountService, model);
    }
}

Assuming that AccountViewModel looks like this:

public class AccountViewModel
{
    public AccountViewModel(IAccountService accountService, AccountModel model)
    {
        AccountService = accountService;
        Model = model;
    }

    public IAccountService AccountService { get; }
    public AccountModel Model { get; }
}

Upvotes: 2

Sir Rufo
Sir Rufo

Reputation: 19096

Exclude the data objects from the constructor and pass the data via an initialization method.

public class AccountModel
{
    public int Id { get; set; }
    // some more properties
}

public interface IAccountService
{
    Task<AccountModel> GetByIdAsync(int id);
}

public class AccountViewModel
{
    public AccountViewModel(IAccountService accountService)
    {
        AccountService = accountService;
    }

    protected IAccountService AccountService { get; }

    private Task LoadFromModelAsync(AccountModel model)
    {
        Id = model.Id;
        _originalModel = model;
        return Task.CompletedTask;
    }

    private AccountModel _originalModel;
    public int Id { get; private set; }

    public async Task InitializeAsync(object parameter)
    {
        switch (parameter)
        {
            case null:
                await LoadFromModelAsync(new AccountModel());
                break;
            case int id:
                {
                    var model = await AccountService.GetByIdAsync(id);
                    await LoadFromModelAsync(model);
                    break;
                }
            case AccountModel model:
                await LoadFromModelAsync(model);
                break;
            default:
                throw new InvalidOperationException();
        }
    }
}

Upvotes: 1

Related Questions