简体   繁体   中英

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.

// Somehow, Unity sees this class and registers the type. public class FooViewModel : ViewModelBaseClass // 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM