Sofa, AvalonDock and MEF
Sofa and MEF !
What is AvalonDock ?
AvalonDock is a WPF controls library which can be used to create a docking layout system like that is present in Visual Studio.
It supports fly-out panes, floating windows, multiple docking manager in same window, styles and themes and it can host WinForms controls.
See more at the AvalonDock web site,
What is Sofa?
Sofa wraps AvalonDock and provides:
- Easier programming
- Enhanced features
- Additional features
See more at the Sofa web site,
What problems does MEF solve?
MEF presents a simple solution for the runtime extensibility problem.
MEF provides a standard way for the host application to expose itself and consume external extensions.
MEF offers a set of discovery approaches for your application to locate and load available extensions.
MEF allows tagging extensions with additonal metadata which facilitates rich querying and filtering.
See more at the MEF web site.
There is a symmetry between the docking layout of Sofa/Avalon and the MEF component architecture : MEF will allow integration of external components that will easily be represented as tabbed or splited windows.
The MEF XFileExplorer example
The example below is based on the MEF FileExplorer which can be found in the MEF preview download (MEF\MEF2_Preview2\Samples\CS\XFileExplorer) and has been "translated" into a set of Sofa components.
It is a basic file explorer with its treeview, its contents pane and 3 additional functionalities, a size pane showing a graphical representation of file sizes, a preview pane and favorites.
It is made of a main component named Shell and one "sub-component" for each functionality.
Once the application is translated into Sofa components and runs in the Sofa container its appearance is not that different.
You can find it as a Component of the SofaExplorer 1.1 example on the download page of the Sofa web site.
But the user can now customize it:
Another additional feature is the XFileExplorer is now a set of Sofa components and it becomes easy to manage many instances of each set using Sofa perspectives (top left menu). A default filepath is associated to each perspective and allows managing filepathes favorites.
The main goal of this documentation is however not to demonstrate hosting an application as a Sofa component can easily provide additional functionalities: It is to show how MEF concepts and Sofa/AvalonDock concepts fits to each other and are easy to implement.
Micro MEF tutorial
The way MEF works is very simple: MEF components, called Composable Parts, declare they are composable parts:
[Export("Microsoft.Samples.XFileExplorer.FileExplorerViewContract", typeof(UserControl))] public partial class PreviewView : UserControl { ...Then the host application registers composable parts using the CompositionContainer.ComposePart() method: In this example all Composable Parts that are in the executing assembly will be registered:
private void Compose() { var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()); var container = new CompositionContainer(catalog); container.ComposeParts(this); }The XFileExplorer example uses a different object, the CompositionBatch, but basically it is the same work.
At last the hosting application can retrieve composable parts: For instance in the XFileExplorer the 2 following lines will make the _views object automatically loaded by MEF at run time.
[ImportMany("Microsoft.Samples.XFileExplorer.FileExplorerViewContract", AllowRecomposition=true)] private Lazy<UserControl, IFileExplorerViewMetadata>[] _views = null;
Sofa and MEF
When the MEF hosting application becomes a Sofa component it is no longer an application but a UserControl. And it looses its App.xaml.cs file where the Compose method is usually stored. This piece of code has to be moved to the main component. It is Shell.xaml.cs in our example.
Sofa has a central repository where all component running in the container are stored. This allows retrieving components registered in the Sofa container instead of components of the executing assembly:
private bool Compose() { var catalog = new AggregateCatalog(); //Use Sofa component list foreach (CmpModel cmp in Container.SofaContainer.CmpModelList) { catalog.Catalogs.Add(new AssemblyCatalog(cmp.ControlDllName)); ...Then Sofa components (ie MEF composable parts) must be loaded in AvalonDock.
The usual way of loading a Sofa component is to use the SofaContainer.OpenComponent method. This creates a new instance of the component and loads it into an AvalonDock window. The return value is an object storing information about the component.
cmpLoaded = Container.SofaContainer.OpenComponent("ComponentName")
When using MEF instances of components are already created. The AddComponent method replaces the OpenComponent method: It uses an already instanciated object.
A cmpModel object is created to store parameters defining the graphical behaviour of the component.
cmpLoaded = Container.SofaContainer.AddComponent(ComponentInstance, cmpModel);
For instance in Shell.xaml.cs:
private void ReloadAllViews() { … //_views stores MEF objects foreach (var view in _views.OrderBy(i => i.Metadata.DockId)) { //Get the instance of current view var childPane = view.Value; … //Prepare a CmModel object as parameter for the AddComponent method CmpModel cmpModel = new CmpModel(); … switch (view.Metadata.Docking) { case Dock.Top: … cmpModel.AvalonPaneGroup = "TopSide"; cmpLoaded = Container.SofaContainer.AddComponent(childPane, cmpModel);And that's it. All the rest of the code of the original example is not impacted when running as a Sofa component. Some lines of code were added to handle Sofa multi-instance and the default filepath associated to each instance but everything needed to convert a MEF application into a Sofa component using MEF is here.
Sofa not only allows creating MEF enabled applications. It adds an interesting feature to MEF applications: Components are deployed separately.
In the original sample all MEF composable parts must be built in the same directory so that the MEF Compose() method can find them. If a new component is added or modified all the application needs to be re-packaged and re-deployed. And all components of the package are deployed without the user can choose which one he wants.
On the contrary, when using Sofa, MEF components are deployed as Sofa components, separately from each other’s. This gives flexibility in application development and deployment. This may also allow users selecting in a toolset the tool or the version of the tool they want to use.
发表评论
6oGn7x Jet Set in Style with Esembles Collection
ySIIy7 Just thought i would comment and say neat design, did you code it yourself? Looks great. Just found here
AsNJAx This is very interesting, You are a very skilled blogger. I have joined your feed and look forward to seeking more of your wonderful post. Also, I have shared your web site in my social networks!
nEg5op My partner and I stumbled over here by a different page and thought I might as well check things out. I like what I see so now i am following you. Look forward to looking into your web page yet again.
sDCHH1 Way cool! Some extremely valid points! I appreciate you penning this post and also the rest of the website is extremely good.
FIdOWM Unfortunately, fanminds did not present at the GSummit, so their slides are not included. I\ ad love to hear more about their projects. Please get in touch! Jeff at gamification dot co
RM5PAw Only wanna input that you have a very nice site, I love the style it really stands out.
tZVkIl you made blogging look easy. The overall look of your site is fantastic, as well
KAgEIm This information is priceless. How can I find out more?
o2Llkz Pretty nice post. I just stumbled upon your weblog and wished to say that I ave really enjoyed browsing your blog posts. After all I all be subscribing to your feed and I hope you write again soon!
gVZrG8 Wow, great post.Much thanks again. Fantastic.
viagra without prescription! Overnight shiping! Click here now and get discount!
44ED1i I was recommended this web site by my cousin. I am not sure whether this post is written by him as no one else know such detailed about my trouble. You are amazing! Thanks!
D1vqCZ I saw a lot of website but I conceive this one has something special in it in it
IXNxum Suspendisse viverra, mauris vel auctor fringilla
8tN1Vq
4QtAai Loving the information on this internet site, you have done great job on the articles.
i2ev0n Very good article.Really looking forward to read more. Great.
P4T2Dr Thanks for the article.Really looking forward to read more. Much obliged.
JCCp7x Really appreciate you sharing this blog post.Much thanks again. Really Cool.
nlhM9x A round of applause for your blog post.Really looking forward to read more.
Yoxjvb Thanks for the blog article.Really looking forward to read more. Want more.
eAgMMx Im thankful for the article.Thanks Again. Fantastic.
2LwZS4 Thanks-a-mundo for the blog article.Thanks Again. Keep writing.
3R8pEw I loved your post. Keep writing.
dNpq59 Wow, great article.Much thanks again. Will read on...
fnsOzb This is one awesome blog post.Thanks Again. Keep writing.
BkSCde A big thank you for your blog post.Much thanks again. Will read on...
dI0lOc Really appreciate you sharing this post.Really thank you! Great.
8QxAxO A round of applause for your blog post.Thanks Again. Will read on...
LGPusO I really enjoy the article post. Awesome.