Ответ 1
Основное отличие состоит в том, что с единицей вы будете явно регистрировать каждый класс, который хотите использовать в композиции:
var container = new UnityContainer();
container.RegisterType<IFoo,Foo>();
container.RegisterType<IBar,Bar>();
...
var program = container.Resolve<Program>();
program.Run();
В MEF, с другой стороны, вы отмечаете классы с атрибутами, а не регистрируете их где-то еще:
[Export(typeof(IFoo))]
public Foo
{
...
}
На первый взгляд это выглядит как незначительная синтаксическая разница, но на самом деле это более важно. MEF предназначен для динамического обнаружения деталей. Например, с помощью DirectoryCatalog
вы можете проектировать свое приложение таким образом, чтобы его можно было расширить, просто отбросив новые библиотеки DLL в папке приложения.
В этом примере MEF найдет и создаст экземпляр всех классов с атрибутом [Export(typeof(IPlugin))]
в данном каталоге и передаст эти экземпляры конструктору Program
:
[Export]
public class Program
{
private readonly IEnumerable<IPlugin> plugins;
[ImportingConstructor]
public Program(
[ImportMany(typeof(IPlugin))] IEnumerable<IPlugin> plugins)
{
this.plugins = plugins;
}
public void Run()
{
// ...
}
}
Точка входа:
public static void Main()
{
using (var catalog = new DirectoryCatalog(".","*"))
using (var container = new CompositionContainer(catalog))
{
var program = container.GetExportedValue<Program>();
program.Run();
}
}
Для размещения таких сценариев динамической компоновки, MEF имеет концепцию "стабильной композиции", а это означает, что когда она попадает в пропавшую зависимость где-то, она просто будет отмечать эту часть как недоступную и будет продолжать композицию в любом случае.
Стабильная композиция может быть весьма полезной, но она также делает очень трудно отладить неудачную композицию. Поэтому, если вам не требуется динамическое обнаружение деталей и "стабильная композиция", я бы использовал обычный контейнер DI вместо MEF. В отличие от MEF, регулярные контейнеры DI выдают четкие сообщения об ошибках, когда отсутствует зависимость.
Также возможно получить лучшее из обоих миров, используя контейнер DI, который интегрируется с MEF, например Autofac. Используйте Autofac для составления основного приложения и MEF для частей, которые должны быть динамически расширяемыми.