Problems using the Ioc

Topics: Questions
Jan 23, 2013 at 1:39 AM

Geert,

I have a project with a DataModel based class that I want use as a model for a UserControls  ViewModel. The UserControl and ViewModel reside in a separate assembly.  I am using MEF and have almost everything working. I use constructor injection to inject the dataModel I want to use as a model, into the UserControl View. Up to this point everything works as expected. The problem comes in trying to set the datamodel as the model for the UserControls ViewModel. I have been unable to find any examples or anything in the documentation  addressing this.

Any help would be appreciated, (I hope this makes sense)

Bob

Coordinator
Jan 24, 2013 at 10:24 AM

Hi Bob,

I don't think I clearly understand what you mean. If you get the model injected (using nested user controls), you can simply set the property value in the constructor. That should be sufficient.

Mar 18, 2013 at 10:47 PM
Geert,

Sorry for the delay in getting back to you (a lot of other issues that I needed to address). Let me try and clarify what I am trying to do. I am building a modular plugin project. The plugin's consist of a UserControl (Catel) and a view model derived from the ViewModelBase. The plugin uses a singleton data object derived from the SavableModelBase class, that is created and maintained by the project app class. The plugin is located in a separate directory.

Now the problem that I am having is the injection of the data object into the view model of the plugin. What is the best approach, MEF, ..? If I use MEF, do I load the MEF container with views or view models? Really spinning my wheels on this.

Thanks Bob
Coordinator
Mar 20, 2013 at 7:15 PM
Hi Bob,

As long as you load the stuff into the same AppDomain, you can re-use the same ServiceLocator instance. I think it is best to share the ServiceLocator over multiple plugins (just like you would do with MEF, but MEF is slow and I don't like it (but you might though ;-))).
Mar 21, 2013 at 1:38 AM
Edited Mar 21, 2013 at 1:39 AM
Geert,

Thanks for getting back to me. I 'm trying to use the ServiceLocator but am running into problems. After doing a lot of reading and hopefully understanding, I first set the view of the module to register with attributes.
    [ServiceLocatorRegistration(typeof(IRequiredModule), RegistrationType.Singleton, "SignalProcessing")]
    public partial class SignalProcessingView : IRequiredModule
The view is a Catel UserControl. Then in the app.xaml.cs file I set the ServiceLocator to AutoRegisterTypesViaAttributes = true;
            var test = ServiceLocator.Default;
            test.AutoRegisterTypesViaAttributes = true; 
When I run the program, the module isn't detected. I assume that I am missing something. Is there something like I do with MEF to tell the ServiceLocator where to find the modules? For example
            // get the external modules
            var moduleCatalog = new DirectoryCatalog("Modules", "*.dll");
            var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());

            var aggretate = new AggregateCatalog();
            aggretate.Catalogs.Add(assemblyCatalog);
            aggretate.Catalogs.Add(moduleCatalog);
            var container = new CompositionContainer(aggretate);

            // satisfy exports and imports
            container.ComposeExportedValue("DisplayConfig", Configuration);
            container.ComposeExportedValue("SignalProcessingConfig", Configuration);
            container.SatisfyImportsOnce(this);

            // compose the modules
            container.ComposeParts(this);
The other question is, how do I load the views after they have been composed by the ServiceLocator?

Please be kind if I have said or done anything stupid, this has been driving me crazy.

Thanks Bob

PS I am using the latest betas from nuget for Catel.
Coordinator
Mar 21, 2013 at 7:51 AM
Hi,

Ah, you are already using the brand new functionality, good :-)

1) It is best to initialize the service locator at application startup:

ServiceLocator.Default.AutoRegisterTypesViaAttributes = true;

2) I see you are creating the containers, but do you actually call Initialize on them?

See this bootstrapper implementation. It uses OnAssemblyResolve to load the assemblies into the app domain.

Especially check out the following 3 methods:
  • CreateModuleCatalog
  • OnAssemblyResolve
  • ResolveAssemblyAndReferencedAssemblies
Mar 21, 2013 at 4:48 PM
Geert,

Can't override the CreateModuleCatalog it is sealed.

Bob
Coordinator
Mar 22, 2013 at 2:15 PM
Then do it in the method where you compose the catalogs. That's the same.