MEFedMVVM with PRISM 4

Today I was looking at PRISM 4 and how it uses MEF as its DI Container and I thought, wouldn’t it be cool if you could use the 2 together?

Update: Please also check out this post to see how you can use the same composition container for both PRISM and MEFedMVVM so that stuff like IRegionManager, IEventAggregator etc can be injected also in MEFed ViewModels

http://mefedmvvm.codeplex.com/workitem/15391

Why would it be cool?

PRISM brings to the table

– Region Manager
– Modules infrastructure
– Many other utilities and services that you can consume

MEFedMVVM brings to the table

– ViewModel injection in XAML
– Design Time vs Runtime services (so that you can inject design time services when in blend)
– ContextAware services such as IVisualStateManager

Having the 2 working together would be awesome. The question is can they work together?

…teasing… suspense … ok enough Smile

The answer is yes and very easily…

How to do it

In PRISM you need to create a bootstrapper that will basically compose your application. MEFedMVVM also has a sort of Bootstrapper where you can specify how you want to compose the MEF composition. So as such all you need to do is to have your PRISM bootstrapper also tell MEFedMVVM how to do the composition.

Let’s start by creating a PRISM bootstrapper

We need a class that inherits from MefBootstrapper and we will need to override a couple of methods. Here is the code to do this

public class Bootstrapper : MefBootstrapper

{

    protected override void ConfigureAggregateCatalog()

    {

        this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));

    }


    protected override void InitializeShell()

    {

        base.InitializeShell();


        Application.Current.MainWindow = (Shell)this.Shell;

        Application.Current.MainWindow.Show();

    }


    #region Overrides of Bootstrapper


    protected override DependencyObject CreateShell()

    {

        return this.Container.GetExportedValue<Shell>();

    }


    #endregion

}

Now lets enable MEFedMVVM

In order to do this we will simple need to implement the IComposer interface from MEFedMVVM and then return the AggregateCatalog property (that is given to us by PRISM)

#region Implementation of IComposer (For MEFedMVVM)


public ComposablePartCatalog InitializeContainer()

{

    //return the same catalog as the PRISM one

    return this.AggregateCatalog;

}


public IEnumerable<ExportProvider> GetCustomExportProviders()

{

    //In case you want some custom export providers

    return null;

}


#endregion

In this case we will return null as the GetCustomExportProviders. This is a feature used if you have some custom ExportProvider you want MEFedMVVM to use.

The last step (which is the actual line of code to enable MEFedMVVM) is where we tell the MEFedMVVM LocatorBootstrapper to use this class as runtime composer.

protected override DependencyObject CreateShell()

{

    //init MEFedMVVM composed

    MEFedMVVM.ViewModelLocator.LocatorBootstrapper.ApplyComposer(this);


    return this.Container.GetExportedValue<Shell>();

}

As you can see I have put that line of code in the CreateShell method so that the Composer is applied as early as possible so that all views can use MEFedMVVM.

 

Now you can start using MEFedMVVM as you would in a normal project… For example in the Shell you can say

<Window x:Class="MEFedMVVMAndPRISM.Shell"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="Shell" Height="300" Width="300"

        xmlns:mefed="http:\\www.codeplex.com\MEFedMVVM"

        mefed:ViewModelLocator.NonSharedViewModel="ShellViewModel">

and the ShellViewModel would be

[ExportViewModel("ShellViewModel")]

public class ShellViewModel

{

    public string Text { get; set; }


    public ShellViewModel()

    {

        Text = "Hello from the ViewModel";

    }

}

Of course here I am not really leveraging MEFedMVVM capabilities, yet the purpose of this post is not to show those capabilities but to show how you can use PRISM and MEFedMVVM together and take what is best from both. To read more on MEFedMVVM visit the codeplex site.

I create a small sample project to showcase both PRISM and MEFedMVVM working together.

Download sample

Capture

Strong naming an assembly without having the actual source code

Today I had a blocking issue, I was in the process of Strong naming my assemblies yet I was referencing a third party assembly that was not strongly named. This cause a compilation error :S what to do????

A colleague David Field sent me 2 command line snippets that do just the thing…

Basically the idea is to use ILDASM.exe (which comes with .net SDK) to convert the dll to il and then use ILASM to make that IL badk into a dll and sign it. (please note you need an SNK file, you can create one easily with the sn.exe or just use one from the other assemblies you are signing)

the magic of ILDASM and ILASM >>

ildasm myassembly.dll /out:myassembly.il

where myassembly is the name of the DLL

and then we convert that IL back in a dll and sign it with ILASM

ilasm myassembly.il /dll /key=MyStringNameFile.snk

Hope you find this useful I sure did

Infusion Malta is looking for talents

 

logo

 

I’ve been working for Infusion for over a year now and I must say, even though I complain a lot (yea I am one of those guys that complains and complains and complains), its truly an amazing place to work! You get to work on cool cutting edge technology projects and to top it off you get to work with awesome people (probably bigger Geeks than you!).

I love the fact that Infusion is open to new ideas, case in point “Infusion Malta”; I was talking to Managing Director of Infusion London and told him “what if we open an Infusion Malta?”, and here we are today 🙂
*P.S Malta is where I was born… more info on Malta can be found be goggling it 😛

So back to the original subject 😛 We are looking into building a small but efficient team in Malta, I call it Infusion SWAT team 🙂 We are looking for both developers and designers…

For Developers >>
1. You must be a Geek
2. Good C# skills
3. open to work on new technologies like Win Mob7 and Surface
3. Want to learn/work on WPF and Silverlight.
4. Willing to work with me 😛

For Designers >>
1. Good in Visual and Interactive design.
2. Want to learn/work on Expression Blend
3. Willing to work with those other strange people… yea I think they call them developers..

Hope I got you all excited and that you’ll send your CV to me at mgrech@infusion.com 🙂

see you in Malta 🙂

Adding more goodies in MEFedMVVM

Thanks to some good feedback from the community and also some really awesome help from Glenn Block and Sasha Barber, I added some new stuff to MEFedMVVM.

The core 3 additions are

– Reloading of design time data in Blend as you compile in Visual Studio (Patch by Chris Szabo)

      Before this patch you had to close and re open Blend everytime you did a change in your ViewModel for Blend to pick up this change. Chris Szabo sent me a code snippet showing me how I could overcome this issue. Very cool Chris!!!!!

– Added a new method in IComposer so that you can specify a list of custom ExportProviders.

      A user of Cinch suggested this feature since he had some ExportProvider he wanted to use in MEFedMVVM for versioning of objects. Now the IComposer has a new method that looks like this

image

You can return a list of ExportProviders or if you do not want to just return null. MEFedMVVM will attach its own ExportProvider even if you return null. (MEFedMVVM uses the ExportProvider for IContextAware services such as IVisualStateManager so that it can inject the View that requested the ViewModel)

– Added 2 new attached properties to make things more clear.

By default Exports in MEF are treated as Shared. This implies that if before you did an [ExportViewModel(“MyVM”] without specifying a [PartCreationPolicy(CreationPolicy.NonShared)] the ViewModel would be exported as a shared item so all imports get the same instance of the ViewModel. Also this implies that the ViewModel would never be garbage collected since MEF will keep its instance alive. The workaround for this would be to specify [PartCreationPolicy(CreationPolicy.NonShared)] where you put the ExportViewModel attribute. Once you know this its all good but if you are new to MEF maybe it is not that obvious that exports are by default Shared. So in order to make this crystal clear I added 2 new attached properties SharedViewModel and NonSharedViewModel, which will impose the CreationPolicy on the ViewModel you want to export (this is like doing the CreationPolicy on the Import if you were doing standard MEF). Glenn Block came up with this idea, kudos to Glenn!!!!

 

Besides these changes I also did some bug fixing here and there and some minor changes as per request …

– Export for ViewModel had an incorrect ImportCardinality. now the ImportCardinality is set to ExactlyOne.
– DataContextAware ViewModels used to call the DesignTimeInitialization 2 times, this is now fixed.
– Exposed the MEFedMVVM CompositionContainer, you can now access the CompositionContainer directly by doing this ViewModelRepoitory.Instance.Resolver.Container. This is useful if you want to get some Exported object from the CompositionContainer that MEFedMVVM is using.
– Fixed issue with ImportMany. This was a problem in the ExportProvider of MEFedMVVM.
– Added propertyObserver. you can see more about this here
– Fixed issue with DelegateCommand (was not hocking automatically to the CanExecute of the Command Manager in WPF)

Hope you enjoy MEFedMVVM and as always keep feedback coming !

INotifyPropertyChanged… I am fed up of handling events just to know when a property changed

The INotifyPropertyChanged is what tells the WPF/SL binding that a property changed and that the binding should be updated. For this purpose its quite good. But what many times we end up doing is; handling the PropertyChanged in code so that we get notified that a property changed. An example is a ViewModel that need to know when a property in the underlying model changed and if it did it will do something to facilitate the View.

Doing this in code is a bit ugly because you base everything on “magic strings”.. something like this

image

Another problem is that if you use an anonymous delegate you need to do loads of tricks in order to unregister to the event.

In order to over come this I created a PropertyObserver that handles these 2 issues. (Please note that there are already others, Philip Sumi has a good one here and  Josh Smith has a good one here. I created my own since I wanted to have extra + different way of doing it). Also this problem can be solved easily using Rx, I am doing this sample so that you do not need to depend on Rx.

The implementation I did is very simple, I created a PropertyObserver class that uses lambdas so that you tell it what property you want to subscribe to and pass an action to do your “Property Changed handling”. What I also did is an attached method so that all objects that implement INotifyPropertyChanged can simple handle the property changed… so the code looks like this

image

One would ask and how do I unregister? is this using weak event pattern? The answer is NO. I wanted to keep it simple and cross platform (for WPF and SL). what you can do is a more Rx approach… basically in RX if you subscibe to something you get an IDisposable in return so that you can Dispose (i.e in our case unsubscribe) when you want like this

image

as you can see here I am wrapping the call in a using statement… but if you need to unsubscribe in any specific state you can store the IDisposable that you get from the Do call and call Dispose to unsubscribe.

Many times you need this for only one time i.e a property changes you do something and you do not want to get called any more times. For this I created a DoOnce. This will unsubscribe for you once the property changes once. The API is very similar and looks like this

image

That’s more or less it.

Big thanks go to Diego Colombo and John Rayner (two champs that work with me) for the help and input they gave me on this 🙂 You rock guys!

You can download the code here.

OR if you have MEFedMVVM download the latest version since its in MEFedMVVM.

MEFedMVVM v1.0 Explained

Introduction

In this post I will cover the basic things you need to know for quickly start building MEFedMVVM powered WPF and Silverlight. For those new to MEFedMVVM here is a quicky on what MEFedMVVM is all about.

MEF is an awesome framework for introducing extensibility in your projects. MEF is built in a generic manner so that you can use it in many different scenarios, example Backend service, ASP.NET application and yes also WPF and Silverlight. Because of MEF being so generic there is no out of the box support for MVVM (example ViewModelLocator so that a View can request a ViewModel to get injected in DataContext, etc…). One of the goals of MEFedMVVM  is to do all the MEF plumbing for you so that you can simple say “I want to Export this ViewModel” and then you can have a View that says “I would like that specific ViewModel” and BANG, MEFedMVVM will do all the plumbing by leveraging the Mighty MEF. Besides this MEFedMVVM has DesignTime Data capabilities. MEFedMVVM is very much Blend Aware so that you can add design time stuff (you’ll read more about this in a later section).

>> Are there any special requirements to use MEFedMVVM?

Yes and no 🙂 All the testing I did was with .NET 4.0 for WPF and Silverlight 4. Having said that there are users of MEFedMVVM using .NET 3.5. Till now no one reported any major bugs but be warned that myself I only tested MEFedMVVM with .NET 4.0 for WPF and Silverlight 4. With regards to MEFedMVVM at design time; only Blend 4 RC or newer are supported by MEFedMVVM, so unless you have Blend 4 RC or newer there is a chance that MEFedMVVM does not work as one would expect (especially with Blend 4 Beta).

>> How stable is the current code?

It’s pretty much stable. I am really pleased to announce that I marked change set 48734 as stable on Codeplex. Myself and some other guys at work are using it already in production projects and till now we did not find any issues. Having said that if you encounter any issue please contact me and I will do the best I can to help out.

>> I am already using an MVVM Framework! Can I use MEFedMVVM side by side?

Do not worry! If you are using an MVVM Framework go on using it, MEFedMVVM can work side by side. I am currently working with some MVVM library authors to provide samples of how to use MEFedMVVM with other MVVM libraries. On the other hand if you want to use MEfedMVVM on its own, well MEFedMVVM  will give you some basic things out of the box as well such as DelegateCommand<T>, Mediator, NotifyPropertyChangedBase and Visual State Management.

How can I start?

Let’s start by having a look at some core things in MEFedMVVM that you will be using to expose ViewModels for View to consume.

So first of all you have to add a reference to MEFedMVVM.WPF/MEFedMVVM.SL depending on if you are in SL or WPF (Api is 100% the same for both platforms!). You also need to add a reference to System.ComponentModel.Composition otherwise VS will not let you use the ExportViewModel or ExportService attribute.

Lesson 1: How to expose a ViewModel so that a View knows how to consume it?

MEFedMVVM: ExportViewModel

 

 

 

 

In order to expose a ViewModel all you have to do is decorate your VM with the ExportViewModel attribute and give the ViewModel a name so that the View can request that ViewModel by using the name you assigned to the ViewModel.

You might be wondering at this point, but how does that work? Well easy, MEFedMVVM is using MEF to get an Import from the Contract name (the name you gave the ViewModel) ignoring the type since a ViewModel can be of any type in MEFedMVVM (this was done like so so that you can have MEFedMVVM working side by side with any other MVVM library. MEFedMVVM does not dictate that your ViewModel has to inherit from any base class). A viewmodel import in MEF terms would look like this [Import(“ViewModelName”]public object ViewModel {get; set; }. Of course this is not how MEFedMVVM is doing it, in order for this to work MEFedMVVM had to quite a bit of plumbing to get this right 🙂

[Advanced] Besides a normal export of a ViewModel can also do a DataContextAware export. This is an advanced feature and there are only few use cases for it. To know know more on what this is read the DataContextAware section in this article.

 

 

Lesson 2: How can a View consume a ViewModel?

image

 

 

In order to make a View consume a ViewModel that you exposed via the ExportViewModel you have to specify it in the attached property ViewModelLocator.ViewModel.

By specifying this property MEFedMVVM will go looking for the ViewModel that has the name you specifying in the attached property.

[Advanced]In case MEFedMVVM does not find the ViewModel you requested it will store a weak reference of the View and the contract name it was requesting so that if a MEF recomposition happens it can satisfy that import and inject the ViewModel. This is a handy feature if you are build Silverlight applications that use Partitioning and downloads parts of the application async.

Where are we?

Well that’s it. With those 2 steps you are pretty much done! Expose a ViewModel and have a View consume it. But for more complex scenarios you need more then that!

Here are some of the main MEFedMVVM features and briefly how to use them… This will enable more complex scenarios, if you just want a ViewModel injected in a View you can stop here.

>> Dependency Injection for Runtime, Design Time and why not have Both if you are lazy 🙂

In a classical MVVM the usual approach is that the ViewModel does logic to facilitate the View. BUT a ViewModel does not do stuff like connecting to a database and get records from the database! That is the responsibility of a backend service which would then be consumed by the ViewModel (via Dependency Injection so that we can mock the service while testing) to get the data and expose it to View. With MEFedMVVM you can have dependency injection of services via standard MEF Imports.
So you can do like this (by using [ImportingConstructor])

image  OR like this

image

As you can see this is standard MEF exports, nothing to it… what is cool is that you do not have to worry about asking the CompositionContainer (or maybe in SL your CompositionInitializer) to satisfy your imports and clutter the code of your ViewModel. MEFedMVVM will do it for you!

The exports can be done via standard MEF exports (i.e [Export]public class MyService { } ), BUT MEFedMVVM has an export attribute of its own specifically for services so that you can control if the Service is injected in Runtime only – DesignTime only or if you want for both (obviously if you want it for both you do not need to use the ExportService because the same behaviour can be achieved via a standard MEF Export, but its there just in case the Framework will start doing something smarter with it in future).

So a Design time service would look something like this ( in this implementation you would make the service return design time data)

image

and for runtime it would be like this (in this implementation you would have your service connecting to the DB/Web Service/ what have you )

image

>> IContextAware services

This is a very powerful technique to have services that are “ContextAware”. What does that mean? what do you mean by context aware? I get a lot of questions on this and I think in the next version of MEFedMVVM will change its name to IViewAware since the context in MEFedMVVM will be the View requesting the service.

The idea is that if your service implements the IContextAware interface of MEFedMVVM, MEFedMVVM will call the InjectContext passing the View that is requesting the ViewModel which requires the service. Confusing isn’t it 🙂 Here is a Diagram that explain what happens

image

 

 

So why is this so cool? Well with this in place you can do really cool stuff. How many times did you have to create an attached property in order to have you View some MVVM friendly thing? Well now instead of an attached property you can have a service and this service will get injected in the ViewModel thus the ViewModel has now much more control then a simple attached property.

A very good example of this is the IVisualStateManager that comes out of the box with MEFedMVVM. Basically with IVisualStateManager a ViewModel can invoke VisualStates on a View with in code without coupling the ViewModel and the View. You can even mock the IVisualStateManager while doing unit testing and do assertions if the ViewModel did not invoke the correct state at the correct time.

Out of the Box MEFedMVVM has 3 IContextAwareServices

>> IVisualStateManager – This is used to invoke VisualStates. This is definitely my favorite and probably the answer to “how do I do animations in MVVM and give full control to the Designer?”

>>IContainerStatus – This was more of an experiment but hey it is quite useful sometimes. Basically the IContainerStatus hooks to the Loaded and Unloaded events of the View and raises its own events. In this manner the ViewModel can do stuff on load of the View (example only load data when the Loaded event is raised and maybe dispose that data when unloaded).

>> IDispatcherService – This is an abstraction on the Dispatcher so that the ViewModel can invoke operation to happen strictly on the Dispatcher thread.

>> More to come 🙂

 

 

 

 

>> Mediator

As such the Mediator has nothing to do with MEF but when it comes MVVM I feel that Mediator is essential! I use it a lot because it is a way of communicating between entities without each entity knowing of the other. Just like an Event Aggregator. What is interesting is how I exposed this in MEFedMVVM. So for starters there is an interface IMediator so that you can mock it as you like. But what is really cool (and this is a MEF feature) is that a MEdiator would only work if the instance is shared. Now a standard MEF import would be creating a new instance of the object being requested by default, BUT if you decorate the Export with [PartCreationPolicy(System.ComponentModel.Composition.CreationPolicy.Shared)] MEF will do some magic and instead of creating a new instance for the service, it will staisfy the import using a shared instance of that class. Of course this technique can be used for any kind of export, so if you every have a service that need to be shared all you have to do is put the PartCreationPolicy on top of the Export to export the service.

DESIGN TIME >> When you say this will work in Blend what exactly do you mean by that?

Let’s say you have a property in your ViewModel and in the constructor of the VM you set this property to some string, let’s say “Hello World :)”. In your View you wire up the View to the ViewModel using MEFedMVVM and in your View, you create a TextBlock and bind to the ViewModel property. When you open up Blend (if not already in it, you will see the text “Hello World :)” rendered on the screen! and yea if you run the app you would also get the same behavior 🙂 Basically the idea is that MEFedMVVM will do a MEF composition for design time as well as at runtime. for design time MEFedMVVM does some clever things to build the composion so that it ensures that all your Views get satisfied with the ViewModels.

For Design Time, MEFedMVVM offers loads of features besides ViewModel injection. Here are some other goodies that come out of the box with MEFedMVVM.

>> Design Time Services (explained above)
If you you want to make sure that your Designer has full Design Time Data and maybe even behaviour you can do this via Design Time Services. In order to do this you have to design your ViewModel (usually all of us do it that way by default to support unit testing) to use Dependency Injection. Besides this you need to create a Service for Design time (just like you would mock a service for your ViewModel for Unit Testing) and expose that service by decorating it with the ExportService attribute and pass ServiceTypes.DesignTime. Your service would look something like this

 

[ExportService(ServiceType.DesignTime, typeof(IIngredientService))]
public class DesignTimeIngredientService : IIngredientService
{
……
}

This is an opt in feature of course but I recommend that you have a look at it and give it a try since it’s really awesome. Basically if it is working at design time it will work at runtime (unless you have a bug in the runtime service of course 🙂 )

>> IDesignTimeAware

image

This interface does some magic at design time and does nothing at runtime. Some times you have some property in the ViewModel (or maybe even some operation) that you need to execute on the ViewModel at Design time. With the IDesignTimeAware you can do exactly that. In order to leverage this feature your ViewModel must implement the IDesignTimeAware interface and this will include a DesignTimeInitialization method. In this method you can write your own code and MEFedMVVM will make sure to invoke that method when the ViewModel is initialized at design time. At runtime this method will be ignored by MEFedMVVM.

 

 

 

>> DataContextAware ViewModels

This is one of my favorite features I must say! The scenario for this feature is very specific. You would want to use this feature if >>

1. You have an implicit DataTemplate (ex: <DataTemplate DataType=”{x:Type my:ViewModelX}”> ) thus at runtime a ViewModel is injected by the WPF runtime but in Blend the designer is left without any design time data!
2.  You have a case of Parent Child ViewModel. Example: You have a ViewModel that has a list of child ViewModels and in the UI you bind to the list of ViewModel in an ItemsControl and have an ItemTemplate to tell WPF/SL how to render that ViewModel.

The above are the 2 case I created this feature for yet of course this can be used for other things if you like!

If we think about the 2 scenarios that I specified above you can immediately see why those scenarios can work at runtime but not at Design Time. The problem is that at design time the designer can be working on only a specific part of the UI (example the Child UI i.e the User Control that renders the ChildViewModel). In this case the ChildView would not have the attached property that asks for a ViewModel to be injected because we would not want to inject a ViewModel as at runtime that ViewModel would be coming from the ParentViewModel. In order to accomplish this the ExportViewModel has a parameter where you can tell it I want the ViewModel only to be injected at design time, BUT I would also like MEFedMVVM to satisfy my imports when at runtime. You specify this by doing so..

image  As you can see by passing true in the constructor for the ExportViewModel, you are setting the IsDataContextAware to true thus you will start leveraging this feature.

At design time this will work just like a normal ExportViewModel, so it will create an instance of the ViewModel and inject it in the View datacontext. But at runtime this will do something more clever. I will hook to the DataContextChanged event (in WPF, in SL this is not available thus it is hooked to the Loaded event. This might affect you depending on how you are setting the ViewModel to the View but it will work for most cases, specifically for the cases I specified above) and satisfy the imports of the ViewModel. The runtime behaviour is really helpful especially if you are using some of the core MEFedMVVM features such as IVisualStateManager.

Tips for Design Time Data

>> If some design time data does not show attach Visual Studio to Blend so you can debug and see what is going on.

>> Many times when you reference assemblies that have Exports you might end up having funny composition errors; If you do not have strongly names assemblies Blend will load multiple version of the same assembly and this usually result in issues at design time. I always try to sign my assemblies so that I do not get such issue at design time + its always a good practice to sign your assemblies anyway

Conclusion

I am now using MEFedMVVM in all my new projects and I am really enjoying it. It enables me to quickly start a project without having to worry, what should I use for Dependency Injection, How do I give Design Time Data to the ViewModel etc etc… Of course this is work in progress so you might stumble upon a bug or 2 🙂 but I am pretty much committed in investing more time on this framework so if you have suggestions or find bugs please do let me know.

I hope you like MEFedMVVM and that it can help you like it is helping me in everyday projects.

Download MEFedMVVM and Samples for usage from CodePlex

MEFedMVVM changes >> from cool to cooler

MEFedMVVM-Logo2After some discussions with Mr. MEF and a lot of MEF “disassembly and learn” sessions with Reflector, I finally managed to refactor MEFedMVVM and make it utilize more the power of MEF…
Besides this I had a change of Vision for MEFedMVVM. There are loads of awesome MVVM libraries out there, MEFedMVVM should not be competing with these and replicating what these libraries do but add on to them by providing ViewModel injections, Design Time vs Runtime services for Design Time Data, IDesignTimeAware ViewModels, IContextAware services and many other stuff …

I am working with the authors of 2 awesome MVVM libraries and soon we will see a Goldlight version using MEFedMVVM and also Cinch MEFedMVVM enabled 🙂 hopefully we will see more side by side usage of MEFedMVVM with other MVVM libraries.

We rebuilt how MEFedMVVM creates the MEF Composition Container …

Composition in MEFedMVVM

Why this huge code refactoring…

Before, MEFedMVVM relied on CompositionInitializer Satisfy imports which was importing all ViewModels and all Services in your solution… The side effect of this was CompositionInitializer relies on calling CompositionHost.Initialize which can only be called once (in Blend this is a bit hard since blend will re invoke static stuff when you rebuild the project). Besides that maybe you do not want to MIX the MEFedMVVM Composition with your own…

To satisfy an import of all the ViewModels and Services MEFedMVVM was relying on ExportFactory<object, IViewModelMetaData/IServiceMetaData>. As you can see this dictates that all ViewModels and Services where exported as type object… This is done implicitly for you from the ExportViewModelAttribute and ExportServiceAttribute. For ViewModels its ok to be exported as type object since you never rely need a ViewModel to be imported in another ViewModel, if you need this you should reconsider because ViewModels should not be coupled together (unless you have a child vm parent vm relation where you usually would create the Child VM from the Parent VM and pass the instance of the parent)*. But when it comes to services sometimes services need to be injected to other services not just to ViewModels… Now if you export the service as type object you cannot rely do a standard MEF import to get it…

*Having said that if you really really need a VM import do a standard Import and specify the ContractName as VMExport{YourViewModelContractName}. so yea you can still get it via a standard import 🙂

This problem is now solved by the MEFedMVVMCatalog. The export for services was done as type object so that MEFedMVVM could get all services and check if they are design time or runtime and depending on that inject the proper service in the ViewModel. Now MEFedMVVM catalog does this automatically because when an import is requested, depending on if its runtime or designtime MEFedMVVM will return the proper services. What is cool is that now you can import services using the standard MEF way.

 [ImportingConstructor]
public SelectedUserViewModel(IMyService service)
{ }

OR

[Import]
public IMyService MyService { get; set; }

Bye bye ServiceLocator and hello MEFness 🙂

As I said before now you can import a Service via standard MEF methods (i.e [Import] or [ImportingConstructor]). This means that your VM does not need to implement the IServiceConsumer anymore or inherit from BaseViewModel. If you are using a framework that already has a BaseViewModel you can continue using it 🙂 If you need a BaseViewModel that simply implements INotifyPropertyChanged MEFedMVVM has NotifyPropertyChangedBase but nothing more… I don’t see MEFedMVVM as a Framework to replace existing MVVM frameworks. MEFedMVVM is now a Framework that can work side by side with any existing MVVM framework that you like.

Being able to specify the imports for the services (and MEF injecting design time or runtime depending on when the VM is created) gives you more flexibility because you can specify things such as CreationPolicy etc. Besides this it means that now Services can be injected into other services etc etc…

So yea now an Export of ViewModel is simple [ExportViewModel(“MyVM”)] or if you need the VM to only be injected at DesignTime because the ViewModel is rendered from a DataTemplate thus the VM instance will already be injected user the DataContextAware VM feature i.e [ExportViewModel(“MyVM”, true)] . Passing true in the export does a bit of magic because it will not create an instance of the VM at runtime but it will still satisy any imports on that VM, at DesignTime it behaves normally i.e it creates the instance of the VM and injects it in the View. This is useful if the VM is being injected via some DataTemplate implicitly.

Bye bye DesignTimeCatalogAttribute for assemblies

Before MEFedMVVM was loading all assemblies that where marked with the DesignTime attribute when in Design Time. The problem with this was that if you forget to put this in your assembly MEFedMVVM would not load your assembly at design time.

The new MEFedMVVM does not require this because it looks at all assemblies checks you is using MEFedMVVM and if the assembly is using MEFedMVVM it loads it… This is done by looking at the reference assemblies of each assembly.

MEFedExportProvider for IContextAware services

THe question you might be asking is, How does MEFedMVVM inject the View to the Services that implement IContextAware?

The answer to this came from Mr. MEF. Create an Export Provider 🙂

MEFedMVVMExportProvider check if the export being injected implements IContextAware and if it does it sets the correct context (which is the View for IContextAware services). The view is given to the provider by the BasicViewModelInitializer/DataContextAwareViewModelInitializer.

StandardContextInjection

DataContextAwareContextInjection

Overriding the Runtime IComposer

The IComposer API changed… now you need to simple return the Catalog that you want MEFedMVVM to use to resolve the ViewModels and Services used by these ViewModels. I created 2 samples with Custom IComposers, 1 in Silverlight and 1 in WPF.

the API for IComposer now looks like this

  public interface IComposer
    {
        ComposablePartCatalog InitializeContainer();
    }

Conclusion

I hope you like the new MEFedMVVM… I am using this library on a large scale project and I am finding it really awesome. I did not make a release of the library yet so that I do a couple of large projects with this library and make sure that if I need to make API changes I can. Yet hopefully there will not be any more API changes since I think this big refactor made MEFedMVVM really light weight.

Let me know if you have any suggestions or if you hit any bugs. THANKS 🙂

Download MEFedMVVM from Codeplex: http://mefedmvvm.codeplex.com/

How does MEFedMVVM compose the catalogs and how can I override the behavior? – MEFedMVVM Part 4

Some content may be out of date. See latest blog on changes made here.

Introduction

As you already know, MEFedMVVM is capable of composing the catalogs for you so that you do not have to worry about it both in Silverlight and in WPF. The composition happens a bit differently in SL and WPF so I will divide the “How to write a composer” section in 2, how it works for SL and how it works for WPF. But first let’s see what is common.

Please Note: This article is for advanced scenarios of using MEFedMVVM if you are using MEFedMVVM with its default behavior you do not need to do this since by default MEFedMVVM does the composition on its own. Yet if you want to have a silverlight app that uses multiple XAP files or a WPF app that is loading dlls that are not referenced by the main application and that reside somewhere else then the exe directory (or even Extensions folder of the base directory).

The LocatorBootstrapper and the IComposers

If you have been looking in the code of MEFedMVVM you’ll know that there is a class called LocatorBootstrapper. This class is responsible of checking if the MEF composition is done and if not I will ask the Composers to do so.

The “Composers” ? What the hell are these??

Basically these are instances of IComposer and there are 2 of these in the LocatorBootstrapper, one for DesignTime composition and one for Runtime. By default MEFedMVVM uses its own implementation of the IComposer which are DefaultRuntimeComposer and DefaultDesignTimeComposer but if you want to do something smarter (I will talk more on this later in the article) you can call the ApplyComposer method of the LocatorBootstrapper and inject a runtime composer that you implement. You must make sure to make this call before anything gets composed. A good place to do this is in the Application class constructor.

In the current version you cannot supply a DesignTime IComposer. I could have made the ApplyComposer API to accept another composer for DesignTime yet this method would be called always too late from Blend. I am currently working on a solution for this. Having said this, I do not see why you would want to override the default DesignTime composer since you still have control. I will talk more on this later in the post but any assembly marked with the DesignTimeCatalog will get picked up and loaded by the DefaultDesignTimeComposer. The only case where you would want to override this behavior is if you want to ignore the DesignTimeCatalog attribute. This is not suggested since not only it will slow down a lot the composition since blend loads many assemblies but it can also cause exceptions in Silverlight. I am open for suggestions so if you have any please let me know.

How can I create a Composer?

You do so by implementing the IComposer interface which looks like this.

   1: public interface IComposer

   2:     {

   3:         bool InitializeContainer();

   4:     }

In the InializeContainer you should put the code to initialize the Container and call CompositionHost.Initialize. (For WPF there is a catch that I will explain in the WPF section of the post).

Understanding and writing a Composer for Silverlight

What do the default MEFedMVVM composer do for SL?

The DesignTimeComposer will load all the assemblies that are decorated with the DesignTimeCatalog attribute in the AppDomain of Blend by using a trick explained here and create a CompositionContainer with MEF AssemblyCatalogs. So even if you have multiple XAP files MEFedMVVM will still get resolved as long as you put the DesignTimeCatalog attribute. If you forget to do this MEFedMVVM will put a message in the output window saying “No assemblies found for Design time. Quick tip… do not forget to put the DesignTimeCatalogAttribute for the assembly that contains your design time stuff. Even if its just a ViewModel you want to load.”. Yet in order to get this you need to have Blend attached with VisualStudio. (I am working hard on a solution to make this more obvious).

The Runtime Composer does not do anything. No really! It does not. The implementation simple returns true in the InitializeContainer method. This is because in SL CompositionInitializer.SatisfyImports (a class that is not present in WPF since WPF does not have System.ComponentModel.Composition.Initialization.dll) will create a container from the existing XAP.

So if you want to override the Runtime behavior for the SL version of MEFedMVVM you do not even have to call LocatorBootstrapper.ApplyComposer because for SL this is not doing anything anyway! But for the code to be the same for SL and WPF maybe its best if you do the call.

Quick Tip: If you are overriding the default container do not forget to add the an assembly catalog for the MEFedMVVM library, if you want to get injected with services that come out of the box with MEFedMVVM such as IVisualStateManager. Here is some sample code that is loading different XAP files

   1: AggregateCatalog aggregateCatalog = new AggregateCatalog();

   2: //add the catalogs for the current assembly and the MEFedMVVM assembly since we are overriding the default behavior

   3: aggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(ViewModelLocator).Assembly));

   4: aggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(App).Assembly));

   5: var listOfPluginXAPs = new[] { "Plugin1.xap" };

   6: foreach (var item in listOfPluginXAPs)

   7: {

   8:     DeploymentCatalog deploymentCatalog =

   9:       new DeploymentCatalog(item);

  10:  

  11:     aggregateCatalog.Catalogs.Add(deploymentCatalog);

  12:  

  13:     deploymentCatalog.DownloadCompleted += (s, args) =>

  14:     {

  15:         if (args.Error != null)

  16:             Debug.WriteLine("Error downloading plugin from " + item + " Exception: " + args.Error);

  17:         if (args.Cancelled)

  18:             Debug.WriteLine("Downloading of plugins was cancelled");

  19:  

  20:         PluginsDownloaded = true;

  21:     };

  22:  

  23:     deploymentCatalog.DownloadAsync();

  24: }

  25: CompositionHost.Initialize(aggregateCatalog);

Understanding and writing a Composer for WPF

What do the default MEFedMVVM composer do for WPF?

The DesignTimeComposer will load all the assemblies that are decorated with the DesignTimeCatalog attribute and create an AssemblyCatalog for each one. If you forget to put the DesignTimeCatalog attribute MEFedMVVM will put a message in the output window saying “No assemblies found for Design time. Quick tip… do not forget to put the DesignTimeCatalogAttribute for the assembly that contains your design time stuff. Even if its just a ViewModel you want to load.”. Yet in order to get this you need to have Blend attached with VisualStudio. (I am working hard on a solution to make this more obvious).

The RuntimeComposer will create a DirectoryCatalog for the AppDomain base directory and also checks if there is an Extensions folder and if so it will create a DirectoryCatalog for that folder as well. So yea if you have a set of plugins that are not being referenced by the main application, you do not even need to override the default behavior since you can make the plugins compile in an Extensions folder and MEFedMVVM will still load those assemblies. This is the code that creates the MEF catalog for the Default WPF Runtime Composer.

   1: var catalog = new AggregateCatalog();

   2: var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;

   3: var extensionPath = String.Format(@"{0}\Extensions\", baseDirectory);

   4: catalog.Catalogs.Add(new DirectoryCatalog(baseDirectory));

   5: catalog.Catalogs.Add(new DirectoryCatalog(baseDirectory, "*.exe"));

   6: if (Directory.Exists(extensionPath))

   7:     catalog.Catalogs.Add(new DirectoryCatalog(extensionPath));

   8: return catalog;

The “catch” with WPF version of MEFedMVVM

WPF does not have System.ComponentModel.Composition.Inialization so as such it does not have CompositionHost and CompositionInitializer but Mr.MEF, Glenn Block created this dll for us over here, and we are using it in MEFedMVVM, thus we benefit from the same code for SL and WPF. The only difference is that you have to do a trick when creating the CompositionContainer. You need to specify the ExportFactoryProvider when creating the CompositionContainer. like so

   1: var provider = new ExportFactoryProvider();

   2: var container = new CompositionContainer(catalog, provider);

   3: provider.SourceProvider = container;

   4: CompositionHost.Initialize(container);

If you fail to do so MEFedMVVM will not resolve the ViewModels and the Services since MEFedMVVM using ExportFactory to get the imports.

Enough talking (well as such its blogging 🙂 ) give us some code!

I did 2 samples one for Silverlight by using DeploymentCatalog to load assemblies from different xap files and one for WPF using DirectoryCatalog to load plugins from a folder called Plugins (this was just to show how you can do it because as such I could made the plugins compile in a Directory called Extensions and it would still have worked).

The source can be found in by download the code from http://mefedmvvm.codeplex.com/SourceControl/list/changesets there is a folder samples where you will find these 2 samples.

Conclusion

As you can see MEFedMVVM can also be used in more advanced scenarios where you want control over the MEF Composition of Catalogs. The default composition will work for most of the apps, yet for some (such as multiple XAP SL applications) you must have control over the composition.

As always feedback is much appreciated.

Download MEFedMVVM and start MEFing it up!

http://mefedmvvm.codeplex.com/

IContextAware services to bridge the gap between the View and the ViewModel – MEFedMVVM Part 3

Some content may be out of date. See latest blog on changes made here.

If you did not have look at MEFedMVVM introduction please so here. I also wrote an article on ExportViewModel here.

So what the hell is an IContextAwareService??

It is a service that knows about its context (which is the UIElement that invoked the import for the ViewModel and the services it depends on).

As I said in previous posts this is one of my favorite feature that MEFedMVVM has. Why well many times I created attached properties to extend UI functionality so that I can do proper MVVM. Yet some times it does not feel right because there is still a gap. The ViewModel does not have control over what the attached property does. Usually this is solved by exposing commands from the ViewModel and then you have another attached property that invokes the command which is magically databound ad what not. An example of something like this is VSM support I did a while ago here.

Enter MEFedMVVM with it’s IContextAwareServices.

You create this kind of service when you want to do some thing to or with the UI Element using the ViewModel as its DataContext. For example let’s say I want to know when the UIElement is Loaded and Unloaded so that my ViewModel does something smart only when you are Loading and Unloading. (please note this is just one example and I choose this example just to show the technique)

So let’s start by creating a service to do this.

First thing we have to do is create a class that Implements IContextAware. So our class will look like this

   1: public class DefaultContainerStatus : IContainerStatus


   2: {


   3:    #region IContextAware Members


   4:


   5:    public void InjectContext(object context)


   6:    {


   7:    }


   8: }

As you can see this interface has a method called InjectContext. This method will be called by MEFedMVVM with the UIElement that is requesting the ViewModel that has this service as Dependency. Since now we have the instance to the UIElement we can hook to the Loaded and Unloaded event and raise our own events that can later be mocked when unit testing the ViewModel.

So let’s create an interface to hide the default implementation of our service

   1: public interface IContainerStatus : IContextAware


   2: {


   3:     event Action ContainerLoaded;


   4:     event Action ContainerUnloaded;


   5: }

and now make the service implement that interface

   1: [ExportService(ServiceType.Both, typeof(IContainerStatus))]


   2: public class DefaultContainerStatus : IContainerStatus


   3: {


   4:     #region IContainerStatus Members


   5:


   6:     public event Action ContainerLoaded;


   7:


   8:     public event Action ContainerUnloaded;


   9:


  10:     #endregion


  11:


  12:     #region IContextAware Members


  13:


  14:     public void InjectContext(object context)


  15:     {


  16:         var element = context as FrameworkElement;


  17:         if (element != null)


  18:         {


  19:             element.Loaded += new RoutedEventHandler(ElementLoaded);


  20:             element.Unloaded += new RoutedEventHandler(ElementUnloaded);


  21:         }


  22:     }


  23:


  24:     void ElementLoaded(object sender, RoutedEventArgs e)


  25:     {


  26:         if (ContainerLoaded != null)


  27:             ContainerLoaded();


  28:     }


  29:


  30:     void ElementUnloaded(object sender, RoutedEventArgs e)


  31:     {


  32:         if (ContainerUnloaded != null)


  33:             ContainerUnloaded();


  34:     }


  35:


  36:     #endregion


  37: }

As you can see here all I am doing is handle the Loading and Unloading of the UIElement and raise the IContainerStatus events. In the code about I am also Exporting the service by using the ExportService attribute which tells MEFedMVVM that this is a service that can be consumed by ViewModels.

And that’s it folks. We are done. Now a ViewModel can start using this service by simple requesting it from the ExportViewModel attribute like so

   1: [ExportViewModel("VM1", typeof(IContainerStatus)]


   2: public class TestViewModel : BaseViewModel

One thing you should not forget is putting the [assembly: DesignTimeCatalog] somewhere in your project, otherwise MEFedMVVM will ignore your project. This is something that is not used at runtime but for design time it is crutial so that MEFedMVVM only loads your projects. MEFedMVVM will ignore any assembly at design time that does not have this attribute set!

Conclusion

There is a lot of potential in this approach. Currently MEFedMVVM exposes some out of the box IContextAware services which are

IViewStateManager – You can use this to invoke Visual States from your ViewModel.

IDispatcher – You can use this service to invoke delegates on the UI thread

IContainerStatus – You can use this service to get loaded and unloaded events.

and many more are coming up. But hey build your own if MEFedMVVM does not give you one already, it’s easy 🙂 and yea we would love to see what you come up with, if you want to contribute we are always happy to have your code 🙂

As always feedback is most appreciated.

Go MEF it up now 🙂 http://mefedmvvm.codeplex.com/