MEF – Managed Extensibility Framework – новая библиотека для создания композитных приложений. То есть приложений, которые собираются из отдельных частей.

Скачать его можно по адресу http://mef.codeplex.com/, версия на момент написания поста – Preview 5. На базе MEF построена Visual Studio 2010.

MEF по функциональности похожа на IoC-контейнеры, но авторы не стремились повторить функциональность существующих контейнеров. В MEF есть несколько уникальных фич, которых нету в  IoC-контейнерах.

Сразу примеры, снова поиск фильмов. Возьмем основной код из поста про Unity.

// Фильм
public class Movie
{
    public string Title { get; set; }
    public string Director { get; set; }
    public int Year { get; set; }
}

/// <summary>
/// Интерфейс репозитария
/// </summary>
public interface IMovieRepository
{
    IQueryable<Movie> GetMovies();
}

// Сервис поиска фильмов
[Export]
public class MovieFinder
{
    IMovieRepository _repository;

    [ImportingConstructor]
    public MovieFinder(IMovieRepository repository)
    {
        _repository = repository;
    }

    public IEnumerable<Movie> FindByTitle(string q)
    {
        return _repository
                .GetMovies()
                .Where(m => m.Title.Contains(q));
    }
}

// Заглушка для репозитария
[Export(typeof(IMovieRepository))]
public class InMemoryMovieRepository : IMovieRepository
{
    public IQueryable<Movie> GetMovies()
    {
        return new[]   
        {   
            new Movie   
            {   
                Title = "Гарри Поттер и узник Азкабана",   
                Director = "Альфонсо Куарон",   
                Year = 2004   
            },   
            new Movie   
            {   
                Title = "Звездные войны: Эпизод 2 - Атака клонов",   
                Director = "Джордж Лукас",   
                Year = 2002   
            },   
            new Movie   
            {   
                Title = "Властелин колец: Братство кольца",   
                Director = "Питер Джексон",   
                Year = 2001   
            },   
        }.AsQueryable();
    }
}  

В коде атрибутами размечены экспортируемые классы и импортирующий конструктор.

Теперь код, который это все использует.

static void Main(string[] args)
{
    //Создание каталога "частей"
    var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());

    //Создание контейнера
    var container = new CompositionContainer(catalog);

    //Получение экземпляра
    var finder = container.GetExportedObject<MovieFinder>();
}

В текущем виде мало отличается от примера с Unity.

На самом деле в MEF гораздо более широкие возможности работы с импортами и экспортами. Экспортировать можно не только классы, но и методы, и значения свойств. Импортировать можно не только через конструктор, но и через свойства и даже через приватные поля (но это не будет работать в частично доверенном окружении).

Упростим пример, класс Movie и Main останутся без изменений.

[Export]
public class MovieFinder
{
    [Import]
    Func<IQueryable<Movie>> _getMovies = null;

    public IEnumerable<Movie> FindByTitle(string q)
    {
        return _getMovies().Where(m => m.Title.Contains(q));
    }
}

public class InMemoryMovieRepository
{
    [Export(typeof(Func<IQueryable<Movie>>))]
    public IQueryable<Movie> GetMovies()
    {
        return new[]   
        {   
            //...
        }.AsQueryable();
    }
}

Также важной фичей MEF является возможность поиска частей в сборках в каталоге на диске, а также мониторинг изменений этих сборок и перезагрузка частей. Кроме того есть API для пересборки частей при изменении.

Но об этом в другой раз.

Теги : IoC, Unity, .NET, MEF