.NET Framework
Управляемая расширяемость
Поиск…
замечания
Одним из больших преимуществ MEF по сравнению с другими технологиями, поддерживающими шаблон инверсии управления, является то, что он поддерживает разрешение зависимостей, которые неизвестны во время разработки, без необходимости в значительной (если есть) конфигурации.
Все примеры требуют ссылки на сборку System.ComponentModel.Composition.
Кроме того, все (основные) примеры используют их в качестве примерных бизнес-объектов:
using System.Collections.ObjectModel;
namespace Demo
{
public sealed class User
{
public User(int id, string name)
{
this.Id = id;
this.Name = name;
}
public int Id { get; }
public string Name { get; }
public override string ToString() => $"User[Id: {this.Id}, Name={this.Name}]";
}
public interface IUserProvider
{
ReadOnlyCollection<User> GetAllUsers();
}
}
Экспорт типа (Basic)
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
namespace Demo
{
[Export(typeof(IUserProvider))]
public sealed class UserProvider : IUserProvider
{
public ReadOnlyCollection<User> GetAllUsers()
{
return new List<User>
{
new User(0, "admin"),
new User(1, "Dennis"),
new User(2, "Samantha"),
}.AsReadOnly();
}
}
}
Это можно определить практически в любом месте; все, что имеет значение, - это то, что приложение знает, где его искать (через создаваемые им ComposablePartCatalogs).
Импорт (основной)
using System;
using System.ComponentModel.Composition;
namespace Demo
{
public sealed class UserWriter
{
[Import(typeof(IUserProvider))]
private IUserProvider userProvider;
public void PrintAllUsers()
{
foreach (User user in this.userProvider.GetAllUsers())
{
Console.WriteLine(user);
}
}
}
}
Это тип, который зависит от IUserProvider
, который может быть определен где угодно. Как и в предыдущем примере, все, что имеет значение, - это то, что приложение знает, где искать соответствующий экспорт (через создаваемые ComposablePartCatalogs).
Подключение (базовое)
См. Другие (основные) примеры выше.
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
namespace Demo
{
public static class Program
{
public static void Main()
{
using (var catalog = new ApplicationCatalog())
using (var exportProvider = new CatalogExportProvider(catalog))
using (var container = new CompositionContainer(exportProvider))
{
exportProvider.SourceProvider = container;
UserWriter writer = new UserWriter();
// at this point, writer's userProvider field is null
container.ComposeParts(writer);
// now, it should be non-null (or an exception will be thrown).
writer.PrintAllUsers();
}
}
}
}
До тех пор, пока что-то в пути поиска сборки приложения имеет [Export(typeof(IUserProvider))]
, соответствующий импорт UserWriter
будет выполнен, и пользователи будут напечатаны.
Другие типы каталогов (например, DirectoryCatalog
) могут использоваться вместо (или в дополнение к) ApplicationCatalog
для просмотра в других местах для экспорта, которые удовлетворяют им.