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