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 для пересборки частей при изменении.
Но об этом в другой раз.
