Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια

Παρουσίαση με Ετικέτες

Όλες οι Ετικέτε... » MEF   (RSS)

An Extensible WPF client layout with RibbonTab submenus using MEF

I was just experimenting with extensibility using MEF (MEF is a .NET resident for .NET4 and SL4), when I created a small proof of this functionality that I could share via my blog. It is a semi-patterned (only for the main shell, my shell, not a PRISM one with viewregions and stuff, just an MVVM main area implemented with MVVMLight), but it does what it is supposed to do. So what is is supposed to do? It is an application, which can be extended by simply, drag and dropping, dlls in the Plugins directory. Every plugin, contains a certain amount, of RibbonTabs and each one, can provide applications, via RibbonTabItems (utilized the Microsoft Ribbon for WPF October 2010). By clicking each one of these items, one can open the corresponding application in the closable TabControl next to the plugin option menu. This menu, by the way is a WPF Outlook bar reused by this codeproject. The Favorites menu is a subset of the Applications option. The plugin system is based on MEF, demonstrating a simple plugin system.

Simple View

image

Extended View

image

So, this application consists of a simple ViewModel which contains all the necessary properties and a simple View, databound to this ViewModel. The most important Bindings are the one of the SelectedPlugin.RibbonTabCollection and the OpenedApplications of the TabControl. Upon selection of a certain tabitem, we switch to the corresponding plugin too (containing the application of the selected item).  Applications are some usercontrols (with codebehind), I constructed randomly and exposed as *concrete* implementations via the plugin mechanism. So, how does this work?

Managed Extensibility Framework

I use two main interfaces, one for Applications…

[code]
public interface IApplication
{
    String ApplicationName { get; set; }
    ContentControl ApplicationView { get; set; }
}[/code]

…and one for plugins.  The interface IPlugin, is marked as InheritedExport (a MEF attribute), mentioning that whoever implements this, can be discovered by MEF and used at some way (discribed below)!

[code][InheritedExport]
public interface IPlugin
{
    ObservableCollection<RibbonTab> RibbonTabCollection { get; }
    ObservableCollection<IApplication> ApplicationCollection { get; }
}

public interface IPluginMetadata
{
    string Name { get; }
    string Version { get; }
}

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class PluginMetadataAttribute : ExportAttribute
{
    public PluginMetadataAttribute(string name, string version)
        : base(typeof(IPlugin))
    {
        Name = name;
        Version = version;
    }

    public string Name { get; set; }
    public string Version { get; set; }
}[/code]

So our plugin has a RibbonTabcollection (again constructing via XAML), and an ApplicationCollection. It also has metadata like the name. This string, is the one, databound in the outlookbar list, providing for the name of the selection via a data template.

[code]<DataTemplate x:Key="PluginItemTemplate">
    <TextBlock Text="{Binding Metadata.Name}" />
</DataTemplate>[/code]

Messaging between views is implemented via a simple Messaging schema, using the provided mechanism of MVVMLight.

The important thing is the AllPlugins property on the ViewModel. It is declared as an observable collection of lazy items, that are constructed upon dereferencing the “Value” property of each Lazy (of IPlugin) instance. How is this dereference achieved? It is achieved for free, by the data binding mechanism. Notice the SelectedValue and SelectedValuePath, pair Smile.

[code]<ListBox ItemsSource="{Binding AllPlugins}"
                         SelectionMode="Single"
                         ItemTemplate="{StaticResource PluginItemTemplate}"
                         SelectedValue="{Binding SelectedPlugin, Mode=TwoWay}"
                         SelectedValuePath="Value" />[/code]

Notice the ImportMany attribute enabling the collection to be populated by the MEF mechanism.

[code][ImportMany]
private ObservableCollection<Lazy<IPlugin, IPluginMetadata>> allPlugins
    = new ObservableCollection<Lazy<IPlugin, IPluginMetadata>>();
public ObservableCollection<Lazy<IPlugin, IPluginMetadata>> AllPlugins
{
    get
    {
        return allPlugins;
    }
    set
    {
        allPlugins = value;
        RaisePropertyChanged("AllPlugins");
    }
}[/code]

Final major question! How are plugins discovered? I have marked a directory on my system as Plugins (via App.config – change that when you run the demo). The catalog, that is going to discover all these types (the ones that are dropped there) is a DirectoryCatalog which can compose all the necessary types.

[code]DirectoryCatalog directoryCatalog =

new DirectoryCatalog(ConfigurationManager.AppSettings["PluginsDirectory"]);

container = new CompositionContainer(directoryCatalog);

//Fill the imports of this object
try
{
    this.container.ComposeParts(this);
}
catch (CompositionException compositionException)
{
    Debug.WriteLine(compositionException.ToString());
}[/code]

At the demo provided you will see that there are two projects, referencing the contract and implementing as needed.

image

This is only, one simple use of MEF. Future work on this demo, could be to provide dynamic discovery of ViewModel and View types, leaving to MEF the instantiation of them, leaving MEF the inversion of control responsibility too!

I hope you enjoyed this first little tutorial for MEF. The same principles can be applied to Silverlight application for discovering XAP’s for example.

Download the demo

Posted: Τετάρτη, 1 Δεκεμβρίου 2010 1:50 πμ από George J. Capnias | 0 σχόλια
Δημοσίευση στην κατηγορία: , , ,

IT Pro | Dev Connections 2010 - "Και Line-of-Business και Rich Internet Applications: The silver side of the moon"

Ευχαριστούμε όσους μας τίμησαν με την παρουσία τους στο IT Pro | Dev Connections 2010, στην παρουσίαση μας (Άγγελος Μπιμπούδης & Μάνος Κελαϊδίτης) με τίτλο "Και Line-of-Business και Rich Internet Applications: The silver side of the moon". Είδαμε πρακτικές και τεχνολογίες για RIA εφαρμογές σε Silverlight, πώς ξέραμε τις επιχειρησιακές εφαρμογές με Silverlight μέχρι τώρα και τι εφόδια έχουμε πια, για να φτιάχνουμε γρηγορότερα και πιο δομημένα web applications, συνδυάζοντας RIA και LoB χαρακτηριστικά.

Προσπαθήσαμε να πούμε όσα περισσότερα πράγματα γίνεται, δίνοντας ένα κβάντο πληροφορίας που μπορεί να χρησιμοποιηθεί άμεσα, ξεκινώντας με WCF Ria Services, MVVM design pattern και MEF για extensibility. Ο χρόνος ήταν περιορισμένος, αλλά πιστεύουμε ότι τα καταφέραμε (φάνηκε και από την αξιολόγηση :D).

Για όσους όμως, πιστεύουν ότι 75 λεπτά δεν έφτασαν (και αλήθεια θα είναι), σχεδιάζουμε να κάνουμε live meeting στο άμεσο μέλλον, οπότε stay tuned.

*Για να τρέξετε τα demos, θα χρειαστείτε: WCF Ria Services, Silverlight Toolkit, Async CTP, RX Extentions, MVVMLight

*Credits to: Guy Smith-Ferrier for the localization reference and material included. He has done a great work on internationalizing silverlight and localization in general. For more check.

ΠαρουσίασηΥλικό-Demos

image

Posted: Τρίτη, 30 Νοεμβρίου 2010 11:42 μμ από George J. Capnias | 0 σχόλια
Δημοσίευση στην κατηγορία: , , ,