3

I was reading the MSDN article on building Composable Applications: http://msdn.microsoft.com/en-us/magazine/ee291628.aspx. I just don't get the point, it seems that it just exposes a contract and a bunch of import/export methods but I am not sure how to use in a practical sense... How is this different from just inheriting from a third-party control/form? Does someone have a practical example they can share to clarify how this could be beneficial as opposed to just inheriting from the third-party control?

OneFineDay
  • 9,004
  • 3
  • 26
  • 37
Denis
  • 11,796
  • 16
  • 88
  • 150

2 Answers2

2

MEF is a dependency injection framework. Simply explained, I would say it is to extend your application at runtime. You can imagine that someone wants to extend your application, after you wrote it, and he could do so by writing its own application and respecting the contracts your application dictates.

To inherit, you need a reference to assemblies that are know in advance. This is not the case for MEF, it uses a contract (an interface) and the assembly can be dynamically loaded in the application. Then you can start forgetting about compiling over and over to add new features to your application. You start to Extend it...

Here is a good tutorial from microsoft: How to: Use MEF with MVC

codea
  • 1,439
  • 1
  • 17
  • 31
  • 1
    MEF is **not** a DI framework, although it can be used as such. MEF is intended for runtime discovery of plugins. See: http://stackoverflow.com/questions/216565/why-exactly-isnt-mef-a-di-ioc-container – Daniel Mann Jul 24 '14 at 19:42
  • Thanks for pointing this out. It seems that MEF is in a sort of gray zone. But for sure, its integration with Microsoft products (from .Net 4) makes it a good candidate for DI because you don't need anything else. – codea Jul 24 '14 at 20:59
  • 1
    There's no grey area -- MEF is not designed to be an IOC container. If you use MEF for IOC, you're misusing it. If you read the link I provided, Glenn Block (who **worked** on MEF at Microsoft) says exactly the same thing. – Daniel Mann Jul 24 '14 at 22:46
1

I kind of get it... This looks like dependency injection... So everything that I want to pass to CompositionContainer.ComposeParts() needs to be marked with the "Export" attribute. Anything that I am expecting ComposeParts() to fill in needs to be marked with the "Import" attribute. So something like this (stupid example, but I think it illustrates the point) First, the references:

imports System
imports System.ComponentModel.Composition
imports System.ComponentModel.Composition.Hosting

And now for the code (notice the "Export" attribute)

Public MustInherit Class Place
      Public MustOverride Property Name as String
End Class

<Export>
Public Class Library
     Inherits Place  

     Public Overrides Property Name as String = "Library"
End Class

<Export>
Public Class Home
      Inherits Place

    Public Overrides Property Name as String = "Home"
End Class

and now "Person" (notice the "Export" attribute):

Public MustInherit Class Person
    Public MustOverride Property Name as String
End Class

<Export>
Public Class Joe
     Inherits Person

     Public Overrides Property Name as String = "Joe"
End Class

<Export>
Public Class Bob
     Inherits Person

     Public Overrides Property Name as String = "Bob"
End Class

and now something interesting we can compose (notice the "Import" attributes - that's where the injection will happen):

<Export>
Public Class WhereAmI
  <Import>
  Public person as Person

  <Import>
  Public place as Place

  Public Sub TellMe()
        Console.WriteLine(person.Name & " is in " & place.Name)
  End Sub
End Class

And now for the composable magic:

Public Shared Sub Main()
    Dim compositionContainer as new CompositionContainer()
    compositionContainer.ComposeParts(new Bob(), new Library(), new WhereAmI())
    Dim whereAmI as WhereAmI = compositionContainer.GetExportedValueOrDefault(Of WhereAmI)()
    whereAmI.TellMe()    'would print "Bob is in Library"'

    Dim compositionContainer2 as new CompositionContainer()
    compositionContainer2.ComposeParts(new Bob(), new Home(), new WhereAmI())
    Dim whereAmI2 as WhereAmI = compositionContainer2.GetExportedValueOrDefault(Of WhereAmI)()
    whereAmI2.TellMe()    'would print "Bob is in Home"'
End Sub
Denis
  • 11,796
  • 16
  • 88
  • 150
  • MEF is **not** a DI framework. http://stackoverflow.com/questions/216565/why-exactly-isnt-mef-a-di-ioc-container – Daniel Mann Jul 24 '14 at 20:06