DCSIMG
November 2009 - Posts - Bnaya Eshet

Bnaya Eshet

Disclaimer

November 2009 - Posts

MEF for Beginner (concept) - part 1

MEF

MEF for Beginner - part 1

this post is the first in a series of posts of How To start using the new MEF (Manage Extensibility Framework).

the series will include simple steps for using MEF on the .NET, Silverlight and Compact Framework platform.

 

the series TOC is available here.

 

MEF Concept

part 1 will focus on the MEF concept, while the following posts will focus on the implementation details.

 
What is MEF?

the MEF framework is the Extensibility (plug-ins) standard for the .NET

The MEF team declare MEF as

The Managed Extensibility Framework (MEF) is a new library in .NET

that enables greater reuse of applications and components. Using MEF,

.NET applications can make the shift from being statically compiled to dynamically composed.

 

The core concept of MEF

MEF Extensibility  CLR 4   The essence of MEF paradigm is built upon the idea of needs and part

  that can be discovered (in order of satisfying the needs).

  MEF assume that application is build from parts, each part may have needs to

  consume other parts, or may be discover and consumed by other.

  in general parts consumers care about the contract and doesn't care about the parts implementation.

 

MEF is using the following terms to address the above paradigm:

    Import: Define needs in term of Contract (the contract present the capabilities that is needed).

    Export: Exposing discoverable parts (that latter can be instantiate and consumed by the Import),

                      the Export is also Contract based.

    Compose: is handle by the MEF engine, it responsible of putting the pieces together
                        (discover and instantiate the matching Exports, and hand it to the Imports).

                        as analogy you can think of it as having Guilds that publish its policy (shoemaker, tailor, ext…),

                        and Peoples that declaring their professions, the MEF infrastructure apply the role of

                        matching the Peoples to their suitable Guilds.

 

MEF Extensibility  CLR 4 

 

MEF Principles

MEF is following Bertrand Meyer's proposed the “Open Closed Principle” which say:

MEF Extensibility  CLR 4

that way you can architecture the your solution to consume unknown implementation of parts.

 

What does MEF bring to the table?

actually MEF is all about breaking the tightly coupled dependencies within your solution

without loosing the type check safeness.

 

Addressing the Unknown

MEF addressing potentially unknown parts using its Compose mechanism which will be responsible

to discover and instantiate the parts that satisfy the needs of the Imports.

 
Show me the Code

the next parts of this series will focus on how to use the MEF framework in more details

and give the practice needed for building your first MEF application.

but i wont live you without having the taste of how does it implement.

for the first taste i will borrow sample from Glenn Block presentation:

the scenario Glenn present is a Rule engine.

the first part is a single Rule that has need for logger.

Code Snippet
  1. [Export(typeof(IRule))]
  2. public class DiscountRule : IRule
  3. {
  4.     [Import]
  5.     public ILogger Logger { get; set; }
  6.     public void Execute(ref double value)
  7.     {
  8.          Logger.Log("Executing rule");
  9.  
  10.          …
  11.     }
  12. }

the code snippet expose the Rule by decorating the class with the Export attribute.

the class declare its needs for logger by decorating the Logger property with the Import attribute.

Note: MEF does not dictate the use of attribute but this discussion is out of the scope of this post.

 

the Rule Engine class has needs to have the rules, so it decorate the Rules properties as follow:

Code Snippet
  1. public class RuleEngine
  2. {
  3.     [ImportMany]
  4.     public IRule[] Rules { get; set; }
  5. }

 

the final step is to compose all parts together:

Code Snippet
  1. static void Main()
  2. {
  3.     var ruleEng = new RuleEngine();
  4.     var container = new CompositionContainer();
  5.     container.ComposeParts(ruleEng);
  6. }

 

Summary

MEF is very flexible and there is many other ways of implementing that task.

in the following post we will learn how to use MEF in both VS 2008 and 2010, and on different platforms.

 

once again i want to thanks Glenn Block for giving me his MEF presentation which help me building this post.

more resources can be found at Glenn Block post



MEF talk by Glenn Block

MEF Talk by Glenn Block

 

Glenn Block gave PDC talk of how to use MEF on Silverlight 4.0 application.

image

the talk cover MEF basics + delay Silverlight loading.

at the end of the talk Glenn ask Ariel Ben Horesh from SELA group

to demonstrate his Prism MEF application.

 

you can learn more about MEF by attending on my session at the SDP.

 

image

Posted: Nov 20 2009, 12:01 AM by bnaya
תגים:

Key notes PDC day 2

Today PDC Key Note important announcement on the Silverlight 4.0 public beta.

in the last few weeks i was reviewing the Silverlight 4.0 labs written by Alex GoleshIdo Flatow and Josh Reuben at SELA.

the Silverlight 4.0 has lot of new features and capabilities.

it is definitely less restricting environment with lot of new opportunities.

one highlight of the Silverlight 4.0 capability is running flash inside Silverlight application

including the capability of using the flash as visual brush (you can break it into separate

parts which keep playing).

 

if you want to lean more on this topic you can come to the SDP lecture

Silverlight - what's new? (by Alex Golesh)

StreamInsight at the PDC

i just came out of the StreamInsight lecture at the PDC.

StreamInsight is new coming framework for handling the very common scenario

of pub/sub for durable events.

it is owned by the SQL Server team but they built it in as a modular component that

can run without any dependency of existence SQL Server (i.e. it can run in memory

without additional installation).

it is still in it Beta 2 stage but it seem very promising.

Posted: Nov 18 2009, 12:49 AM by bnaya
תגים:

Key note

The PDC09 Key Notes session was somewhat not innovative.

 

anyway the few notes that i find interesting is:

  • Dalas technology: seem  interesting, it simplify access to bank of data repositories via generated service proxy
  • SQL Azure Data Sync, and Project Sydney: help us to extend our on promises SQL Serer data during peek time to the cloud (SQL Azure)
Posted: Nov 17 2009, 09:26 PM by bnaya
תגים:

MEF dinner and Glenn

Finally i had the opportunity to meet Glenn Block.

Glenn is a PM for the new Managed Extensibility Framework in .NET 4

we have spoke of a few aspect related to the MEF technology,

also i cannot cover all the issues spoken in this post, i would like to

note one of Glenn comment about classic MEF scenario that exceed the scope of the IoC world.

 

the scenario is speaking about having plug-ins that may have their own

dependencies which your application doesn't aware of.

this case is not the classic IoC scenario because the IoC declaration

has no information about the dependencies of the dependencies

(the second level of abstraction).

 

so in this case dependencies declaration may not fit, and other

discovery method should be considered.

Posted: Nov 17 2009, 11:13 AM by bnaya
תגים:

MEF lecture was added to the SDP

This post is informative rather technical as i use to.

I'm attending the PDC as part of the SELA group.

in the next 3 next days i will try to keep you inform.

 

first i glad to inform you that the SDP (SELA Developer Practice) will have new MEF session.

as far as i know this is the first session that was composed for Israeli audience.

you may choose to attend in the session from the following reasons

 

Learn the concept behind MEF, where does it fit and why you shouldn’t ignore it.
see haw can you build loosely coupled, extensible solution with less effort you possibly imagine.
understand how MEF can reduce the maintainability cost and supply real value in term cleaner code and new possibilities.

in the base line, the session will help you to have your first step into the MEF world.

Posted: Nov 17 2009, 10:39 AM by bnaya
תגים:, ,

MEF Recomposition

thinking about MEF as another IoC container led us into misconception.
MEF design goal was being a generic extensibility infrastructure,
its just happens that it overlap with the IoC world (and yes it has most of the IoC feature).

this post address the challenge of building extensions over none CLR types (like image files)

from the technical perspective it will discuss the following techniques:

the source code for this post can be found here.

 

Prerequisite

this is advance post which assume basic understanding of the MEF technology (for MEF introduction read this post).

 

Our Test Case

in order to demonstrate the above techniques I choose common scenario of building
very simple WPF application that display pictures which came from heterogeneous data source providers.

image

The Solution Modeling

image

ComponentModel.Initialization.dll

this components design by the MEF team as centric handle for the MEF container functionality

(i did very minor changes to the CompositionHost class, basically exposing the underline container as Export Provider)

ImageExportProviders.dll

this is the heart of this post,.

Export providers (not the catalog) is the underline MEF unit that responsible for the instantiation of the exported parts.

the different providers implementations (local, Picasa, Fickr) has the knowledge of
how to instantiate the discovered photo files into CLR type that implement IPhotoInfo.

MEFPhotoDataSourceProvider

this class is responsible for abstracting the WPF application from it actual photos sources.

WpfImageViewerUI.exe

is the UI implementation

 

Application flow

from this point i will start to explain the different techniques used in the application,
starting with the UI.

 

UI (WpfImageViewerUI  project)

    App.xaml

At the code behind level, it initial the Container with custom MEF Export Providers

and pass the container to the Composition Host (the composition host used as

the default container, it is reachable from anywhere in the code)

Code Snippet
  1. protected override void OnStartup(StartupEventArgs e)
  2. {
  3.     base.OnStartup(e);
  4.  
  5.     var providers = new ExportProvider[] {
  6.         new LocalImageExportProvider("Images", "*.jpg"),
  7.         new PicasaImageExportProvider(URL_PICASA_GENERAL),
  8.         new FlickrImageExportProvider(URL_FLICKR_PEOPLE)
  9.     };
  10.     var container = new CompositionContainer(providers);
  11.  
  12.     CompositionHost.InitializeContainer(container);
  13. }

At the Xaml level we embed the Style.xaml

Code Snippet
  1. <Application.Resources>
  2.     <ResourceDictionary>
  3.         <ResourceDictionary.MergedDictionaries>
  4.             <ResourceDictionary Source="Style.xaml" />
  5.         </ResourceDictionary.MergedDictionaries>
  6.     </ResourceDictionary>
  7. </Application.Resources>


     Style.xaml

For better separation between the graphical designer and the developer, I'm using the style.xaml
as the designer own xaml (only the designer should touch this file, he can change styles and templates).


     PictureShell.xaml

this is the developer own xaml, which the designer shouldn't touch.

it should contain the minimal xaml needed, from the functionality perspective

(it should not have any beauty factor actually it should be really ugly without the style.xaml)

Code Snippet
  1. <Window x:Class="Bnaya.Samples.PictureShell"
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.         xmlns:local="clr-namespace:Bnaya.Samples.Data..."
  5.     Title="PictureShell" Height="300" Width="600">
  6.     <Window.DataContext>
  7.         <local:MEFPhotoDataSourceProvider/>
  8.     </Window.DataContext>
  9.  
  10.     <ListBox x:Name="_lst" ItemsSource="{Binding IsAsync=True}" />
  11. </Window>

  
as you can see it kept short, clean and easy to understand.

from the debugging perspective you can disembed the style.xaml and check whether the
bug came from the functionality or the design.

this xaml contain:

    ListBox declaration
    MEFPhotoDataSourceProvider (which is the binding source of the list's ItemSource)

 

UI.Components (define the MEFPhotoDataSourceProvider class)

as we mention earlier we using data source provider to abstract the actual origin of the data.

the xaml won't have to be changed whenever adding or removing data sources.

another benefit is the ability of a-sync loading (data source that expose hundreds of photos cannot expose synchronously)

Code Snippet
  1. public class MEFPhotoDataSourceProvider : DataSourceProvider
  2. {
  3.     private ObservableCollection<IPhotoInfo> _photos =
  4.         new ObservableCollection<IPhotoInfo>();
  5.     public MEFPhotoDataSourceProvider()
  6.     {   // register for MEF ewcomposable discovery
  7.         CompositionHost.Host.ExportsChanged += OnPhotosChangedHandler;
  8.     }
  9.  
  10.     protected override void BeginQuery()
  11.     {   // a-sync initialization
  12.         ThreadPool.QueueUserWorkItem(Init);
  13.     }
  14.  
  15.     [ImportMany(typeof(IPhotoInfo), AllowRecomposition = true)]
  16.     private IEnumerable<Lazy<IPhotoInfo>> PhotosInternal { get; set; }
  17.  
  18.     private void Init(object state)
  19.     {
  20.         PartInitializer.SatisfyImports(this); // load the picture through MEF
  21.         PhotosInternal.ForEach(lazy => _photos.Add(lazy.Value)); // add
  22.         base.OnQueryFinished(_photos);
  23.     }
  24.  
  25.     private void OnPhotosChangedHandler(object sender,ExportsChangeEventArgs e)
  26.     {
  27.         foreach (var expDef in e.AddedExports) {
  28.             if (expDef.Metadata.ContainsKey("Export")) {
  29.                 Invoke(() =>
  30.                 {
  31.                     Export exp = expDef.Metadata["Export"] as Export;
  32.                     _photos.Add(exp.Value as IPhotoInfo);
  33.                 });
  34.             }
  35.         }
  36.     }
  37. }


    at line 15, you can see that we using the ImportMany decoration with AllowRecomposition = true 
this is the key of the a-sync capabilities (lazy loading).
you can download the source code from here and run the application with and without AllowRecomposition 
in order to see its effect.

    at line 20, PartInitializer.SatisfyImports(this) is actually asking the default MEF container (which we define at the app.xaml)
for the discovered export parts that match the import.

    at line 22, we introduce the base class with our data source collection.

    at the constructor level line 7, CompositionHost.Host.ExportsChanged += OnPhotosChangedHandler we register to the
default  MEF container changed event (again the a-sync lazy loading)

    at the OnPhotosChangedHandler, line 25, we adding any new composed instances into the bind-able collection.

 

Finally we got into the heart of extensibility model, the Export Providers

we use custom Export Provider for discovering none CLR entities (in our case photo files) and introduce it to the CLR world
via the MEF infrastructure as instances that implement IPhotoInfo.

the ImageExportProviders project contain 4 files (one base class and 3 providers)

    ImageExportProviderBase is the provider base class

Code Snippet
  1. public abstract class ImageExportProviderBase : ExportProvider
  2. {
  3.     protected static readonly string CONTRACT_NAME = typeof(IPhotoInfo).FullName;
  4.     protected readonly string _path;
  5.     public ImageExportProviderBase(string path) {
  6.         _path = path;
  7.     }
  8.     protected override IEnumerable<Export> GetExportsCore(
  9.         ImportDefinition definition, AtomicComposition atomicComposition)
  10.     {
  11.         IEnumerable<Export> exports = null;
  12.         if (definition.IsRecomposable) // Async
  13.             ThreadPool.QueueUserWorkItem(LoadPhotos, definition); // we will use recomposition
  14.         else
  15.             exports = OnLoadPhotos(definition);
  16.  
  17.         return exports;
  18.     }
  19.     protected abstract IEnumerable<Export> OnLoadPhotos(ImportDefinition definition);
  20.     private void LoadPhotos(object state) {
  21.         OnLoadPhotos(state as ImportDefinition);
  22.     }
  23.     protected void IntroduceNewExport(Export e) {
  24.         var metadata = new Dictionary<string, object>();
  25.         metadata.Add("Export", e);
  26.         var expDef = new ExportDefinition(CONTRACT_NAME, metadata);
  27.         using (var atomic = new AtomicComposition())
  28.         {
  29.             var argsChanging = new ExportsChangeEventArgs(
  30.                 new ExportDefinition[] { expDef }, new ExportDefinition[0], atomic);
  31.             atomic.AddCompleteAction(() => { });
  32.             base.OnExportsChanging(argsChanging);
  33.             atomic.Complete();
  34.         }
  35.         var argsChanged = new ExportsChangeEventArgs(
  36.             new ExportDefinition[] { expDef }, new ExportDefinition[0], null);
  37.         base.OnExportsChanged(argsChanged);
  38.     }
  39. }

The GetExportsCore is what we have to override when creating custom Export Provider.
you can see at line 12, that we check whether the import definition is recomposable and act accordingly.

in case of recomposable the IntroduceNewExport method is where we notify about the new available exports.

the 3 derived class is just a parser for specific source type.


    LocalImageExportProvider discover and parse file on the local file system.

    FlickrImageExportProvider discover and parse file from the Flickr web site.

Flickr API does not support thumbnails, which results that pictures discovered on Flickr will appear with delay.

    PicasaImageExportProvider discover and parse file from the Picasa web site.

Conclusion

the MEF ability to compose beyond the CLR world is one of its underline extensibility design that
differentiate MEF from typical IoC containers.

and we can use MEF to abstract our data sources achieving a-sync and loosely coupled advantage.

 

the source code for this post can be found here.

Posted: Nov 05 2009, 11:59 PM by bnaya | with 6 comment(s)
תגים:, ,