C# It !

Miky Petrescu Blog

February 21st, 2011

Composable Application – Lazy Loading with MEF

1 Comment, WPF/Silverlight, by Miky.

Today I would like to talk about lazy loading of application parts.

When we use the [Import] or [ImportMany] attributes we are telling MEF to fill our variable with an instance of our desired type. This approach is great if we are dealing with small types, or we are certain that we need this instance, but what if the type we want to import is quite heavy and it would be a waste to load it right on the start? What if we want to import the types based on some user settings or a plug-in system?
The solution for this is using Lazy !

Lazy – “Is wrapper class that provides lazy initialization semantics for any class library or user-defined type.” (MSDN)
The Lazy class will instantiate the T type when we read its Value property or call its ToString() method.

MEF knows to work with Lazy out of the box, and it’s pretty easy to do so.
If we will continue my previous post, instead of importing this way:

[ImportMany(typeof(IModule))]
private List<IModule> _modules;

We would do something like that:

[ImportMany(typeof(IModule))]
private List<Lazy<IModule>> _modules;

This way, when the OnImportsSatisfied method is called, our _modules variable will be filled with Lazy
In order for us to instantiate a module we will have to read the Value property like that:

IModule firstModule=_Modules[0].Value; //Only now our imported module will be instantiated. Since we read its Value property

But here comes the question: “How would you know which module to load?”
In order to identify the modules I “lazy imported”, we will have to provide a metadata to each exported type using the [ExportMetadata] attribute.

[Export(typeof(IModule))]
[ExportMetadata("Name", "Gui Designer")]
[ExportMetadata("RequiresAdmin", true)] //Just to demonstrate you can use any type in the metadata
public class GuiDesignerViewModel : IModule
……

Ok, so now that we have some metadata in our exported types we will have to define an interface for it. (its usage will be explained bellow)

public interface IModuleMetadata
{
    string Name { get; }
    bool RequiresAdmin { get; }
}

And change our lazy import definition to include the metadata.

[ImportMany(typeof(IModule))]
private List<Lazy<IModule, IModuleMetadata>> _modules;

That’s it !
MEF will automatically fill our IModuleMetadata with the values we set with ExportMetadata, without instantiating the type itself.

In order for us to check which module we want to load, we can check the lazy metadata.

public void OnImportsSatisfied()
  {
        foreach (Lazy<IModule, IModuleMetadata> module in _modules)
        {
                if(module.Metadata.RequiresAdmin==false)
                {
                    Debug.WriteLine("Module loaded: " + module.Metadata.Name);
                    _loadedModules.Add(module.Value); //Will create an instance
                }
            }
  }

Or we can instantiate it when we actually need it!

private void ShowModuleExecuted()
        {
            WindowManager windowManager = new WindowManager();
            Lazy<IModule, IModuleMetadata> selectedModule = _selectedModule;
            IModule moduleToLoad = selectedModule.Value; //Only now we instantiate the module
            windowManager.Show(moduleToLoad);
        }

December 31st, 2010

Composable Application – Using MEF and Caliburn Micro

7 Comments, WPF/Silverlight, by Miky.

Introduction

Caliburn Micro is a micro-framework for WPF, Silverlight and WP7 giving us great features for developing all sort of MVVM based application. Either you are developing a simple app or a complex one with composable module parts like Outlook, you will find CM to be fastest way to develop it, while keeping a true MVVM architecture.

Modularity and Dependency Injection
When we develop an application which consist of multiple modules, we need to keep each module as an Independent block. Let’s take “Visual Studio” for example.  In Visual Studio you have a C# document editor, GUI designer, Resource designer etc.  We can think of each of them as module that Visual Studio is loading when needed. Such modules can be added, removed or replaced by a new version without recompiling the whole application. It’s sort of a plug-n-play system, or a Lego blocks if you want.

We achieve this functionality using MEF (Managed Extensibility Framework).
But here’s a few important definitions when dealing with composable application:
Bootstarpper - The object which initialize a composable application.
Container – Keeps a collection of all modules and parts.

For our sample project I defined a simple interface in a separate project, which contains all interfaces. This way we keep a separation between the application and it’s modules:

public interface IModule
{
    string DisplayName { get; }
}

Each module I make will have to implement this interface and export it, so the bootstrapper will find it as a composable part and add it to the container.

[Export(typeof(IModule))]
public class DocumentEditorViewModel : IModule
{
	public string DisplayName
	{
		get { return "My Document Editor"; }
	}
}

This document editor class is defined in a separate project, and has a reference ONLY to the interfaces project.

On my main application I can import all modules easily like that :

public class ShellViewModel : IShell ,IPartImportsSatisfiedNotification
{
        [ImportMany(typeof(IModule))]
        private IEnumerable<IModule> _modules;

        public ShellViewModel()
        {

        }
        #region IPartImportsSatisfiedNotification Members
        public void OnImportsSatisfied()
        {
		//executes when MEF finished loading my modules
        }
        #endregion
}

[ImportMany(typeof(IModule))] attribute tells MEF to fill all Exported IModule objects, and construct them. You should not relay on the MEF to fill it on constructor, instead you implement the IPartImportsSatisfiedNotification. This way MEF will call the OnImportsSatisfied method when it finished loading all imports.
(For importing on constructor, check for [ImportingConstructor] attribute.)

Projects Dependencies

View Injection
Caliburn Micro helps us keeping a separation between the View and the ViewModels by automatically finding the right View (either a UserControl or Window) for the viewmodel.
For example, in the above example we had a DocumentEditorViewModel which was loaded dynamically using MEF as a IModule, Now I’ll create a new WPF window and name it DocumentEditorView and use Caliburn Micro “WindowManager” to display it like that:

private void ShowModuleExecuted()
{
	WindowManager windowManager = new WindowManager();
	windowManager.Show(_selectedModule); //_selectedModule is set from the list of modules
}

If for example the _selectedModule object is DocumentEditorViewModel, WindowManager will look for a Window/UserControl type named DocumentEditorView, instantiate, display it and set _selectedModule as its DataContext! all that in a couple of simple lines.
Caliburn is using name convention for finding the proper View, but it’s not a must. You can simply implement IViewAware in the ViewModel and pass the View manually.

This is just a drop in the ocean of Caliburn Micro and MEF, and I will extend this subject and sample in upcoming posts.

Just one last thing..
I’ll be very happy to answer any question you got and appreciate any comment on my first blog post ! :)

Miky.