Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Satisfying imports for an existing object using MEF

Tags:

c#

mef

Given an arbitrary already existing object which is attributed with [Import] tags, what's the tambourine dance I have to do in order to get MEF to fill in the imports?

Much of the blog documentation seems to be built against preview versions of MEF and don't work anymore - I'm using the released one that's part of .NET 4.0 (or alternatively, MEF 2.0 Preview 3).

AggregateCatalog _catalog;
CompositionContainer _container;

public void Composify(object existingObjectWithImportTags)
{
    lock(_container) {
        var batch = new CompositionBatch();

        // What do I do now?!?!
    }
}
like image 358
Ana Betts Avatar asked Apr 04 '11 21:04

Ana Betts


People also ask

How does MEF work?

The Managed Extensibility Framework or MEF is a library for creating lightweight, and extensible applications. It allows application developers to discover and use extensions with no configuration required. It also lets extension developers easily encapsulate code and avoid fragile hard dependencies.

What is MEF components in visual studio?

Managed Extensibility Framework (MEF) is a component of . NET Framework 4.0 aiming to create lightweight, extensible applications. It aims to allow . NET application developers to discover and use extensions with no configuration required.

What is ImportingConstructor?

By using [ImportingConstructor] , you allow one class that serves as an export to import its dependencies. This dramatically simplifies the architecture, as you can decouple the dependencies of a concrete object from its implementation.


2 Answers

MEF resolves Imports (through property or constructor injection), along whith their own dependencies, from exported types in the registered assemblies registered in the catalog (including the current assembly).

If you want to create an object directly (using the new keyword), or in case the export wasn't ready at the time of the creation, you can use the container to satisfy the imports of an object, using:

_container.SatisfyImportsOnce(yourObject);

I've put together a little scenario doing just that. here's the code:

public class Demo
{
    private readonly CompositionContainer _container;

    [Import]
    public IInterface Dependency { get; set; }

    public Demo(CompositionContainer container)
    {
        _container = container;
    }

    public void Test()
    {

        //no exported value, so the next line would cause an excaption
        //var value=_container.GetExportedValue<IInterface>();

        var myClass = new MyClass(_container);

        //exporting the needed dependency
        myClass.Export();

        _container.SatisfyImportsOnce(this);

        //now you can retrieve the type safely since it's been "exported"
        var newValue = _container.GetExportedValue<IInterface>();
    }
}

public interface IInterface
{
    string Name { get; set; }
}

[Export(typeof(IInterface))]
public class MyClass:IInterface
{
    private readonly CompositionContainer _container;

    public MyClass()
    {

    }
    public MyClass(CompositionContainer container)
    {
        _container = container;
    }

    #region Implementation of IInterface

    public string Name { get; set; }

    public void Export()
    {
        _container.ComposeExportedValue<IInterface>(new MyClass());
    }

    #endregion
}

Now, just use new Tests(new CompositionContainer()).Test(); to start the demo.

Hope this helps :)

like image 117
AbdouMoumen Avatar answered Sep 23 '22 02:09

AbdouMoumen


_container.ComposeParts(existingObjectWithImportTags);

ComposeParts is an extension method that you are looking for.

It simply creates a CompositionBatch and calls AddPart(AttributedModelServices.CreatePart(attributedObject)) and then calls _container.Compose(batch).

like image 35
Wes Haggard Avatar answered Sep 19 '22 02:09

Wes Haggard