Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prism, Unity and default type registration in Modules

Technologies

  • C# 4.0
  • Prism 4 with Unity for DI
  • WPF
  • MVVM

Preface

There are two projects in my solution, MyApp.Shell and MyApp.ModuleFoo

MyApp.Shell's Unity Bootstrapper

protected override IModuleCatalog CreateModuleCatalog()
{
    // Module assemblies are read from a directory.
    DirectoryModuleCatalog moduleCatalog = new DirectoryModuleCatalog();
    moduleCatalog.ModulePath = @".\Modules";
    return moduleCatalog;
}

The project MyApp.ModuleFoo contains a View and a View Model.

The ViewModel

// Somehow, Unity sees this class and registers the type.
public class FooViewModel : ViewModelBaseClass
{
    public string FooText
    {
        get { return "Foo!"; }
    }
}

The View

<Label Content={Binding FooText} />

The View's Code-behind

// Unity automatically sees this as Constructor Injection, 
// which is exactly what I desire.
public FooView(FooViewModel viewModel)
{
    DataContext = viewModel;
    ...
}

MyApp.FooModule's Initialization

Perhaps registering FooView with the region manager is inadvertently registering FooViewModel with Unity?

public void Initialize()
{
    var regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();
    regionManager.RegisterViewWithRegion("FooRegion", typeof(FooView));
}

The view correctly displays "Foo!".

Problems

  • How do I tell Unity to register only a single instance of FooViewModel?
  • Additionally, (and I'm thinking ahead here), how would I tell unity not to register FooViewModel?

Thanks for the help.

Edit:

Added MyApp.FooModule's Initialization code

Edit (Solution):

It turns out RegisterViewWithRegion has two overloads. From Prism's documentation, when the overload I'm using is used, a new instance of the view is created. I'm assuming this also creates a new instance of FooViewModel.

The other overload uses a delegate to resolve FooView. The documentation says this overload is used in the "ViewModel-first" approach. I'm going to make this question as answered, but if anyone has any additional insight, I'd love to hear.

like image 404
Nick Carlson Avatar asked Mar 14 '26 02:03

Nick Carlson


1 Answers

// Somehow, Unity sees this class and registers the type. public class FooViewModel : ViewModelBaseClass ...

I am surprised that you say this as Unity does not register types inside the container by default. You have to tell it to do so either programmatically or in the config file.

When you have concrete classes (not interfaces) they will automatically get created by Unity whether they are registered or not. If not the default behavior is to create a new instance each time. No lifetime management is applied also.

As far as your questions:

To register only one type within your initialisation of your module just have.

Container.RegisterType<FooViewModel>(new ContainerControlledLifetimeManager());

The lifetime manager will instruct unity to only create one instance of the view model.

like image 174
aqwert Avatar answered Mar 16 '26 15:03

aqwert



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!