|
Hi - hope this isn't derailing the thread, but one other change between the Beta and RC of .NET for Metro style apps
relates to the use of MEF. I'm not sure if it will affect existing Caliburn apps, but thought I'd mention it here since MEF is used extensively with Caliburn on other platforms.
Building a bootstrapper for the new MEF version is relatively straightforward, but the MEF team is here to help if there are any challenges. I've investigated what changes are required to make the default WPF template work with this package, the bootstrapper
code seems like it will be identical for Metro style apps. I haven't verified anything more than that the app runs, so please forgive any obvious errors :).
First, the Microsoft.Composition NuGet package needs to be installed.
Then, some basic namespace changes to move from System.ComponentModel.Composition to System.Composition:
using System;
using System.Collections.Generic;
using System.Composition;
using System.Composition.Convention;
using System.Composition.Hosting;
using Caliburn.Micro;
Configuring the bootstrapper is a little simpler than the previous version. Some changes are required so that the window manager and event aggregator can be created by MEF rather than passed in as preexisting instances.
Instead of storing the container, we store an ExportFactory that creates new composition contexts. This is a guarantee against memory (reference) leaks: as some will know, MEF holds references to IDisposable parts. The changes between Beta and RC are driven
partly by the need to make dealing with this more predictable. By creating a new composition context for each service lookup, we ensure that disposable, non-shared parts can be garbage collected along with the context object.
public class AppBootstrapper : Bootstrapper<IShell>
{
ExportFactory<CompositionContext> contextFactory;
protected override void Configure()
{
var defaultPartConventions = new ConventionBuilder();
defaultPartConventions.ForTypesMatching(t => true)
.Shared()
.ExportInterfaces();
var container = new ContainerConfiguration()
.WithAssemblies(AssemblySource.Instance)
.WithParts(new[] { typeof(WindowManager), typeof(EventAggregator) }, defaultPartConventions)
.CreateContainer();
contextFactory = container.GetExport<ExportFactory<CompositionContext>>();
}
private CompositionContext CreateCompositionContext()
{
return contextFactory.CreateExport().Value;
}
The remaining changes just switch over from from the AttributedModelServices-style APIs to use the simple overloads of GetExport(), GetExports() and SatisfyImports(). These have the exact behaivor required by Caliburn by default, so the extra work required
by the earlier version is eliminated.
protected override object GetInstance(Type serviceType, string key)
{
return CreateCompositionContext().GetExport(serviceType, key);
}
protected override IEnumerable<object> GetAllInstances(Type serviceType)
{
return CreateCompositionContext().GetExports(serviceType);
}
protected override void BuildUp(object instance)
{
CreateCompositionContext().SatisfyImports(instance);
}
}
Finally, any parts that have to be shared need to be explicitly marked with the [Shared] attribute. More details on what we've done in this release are in the blog post above. Instructions on migrating from the Beta version of MEF for Metro style apps are
on the MEF wiki.
Hope this helps, we'd love to hear about your experiences, and please get in touch with any questions.
All the best!
Nick (from the MEF team)
|