Я только начинаю изучение DI (я работаю над WPF/Silverlight, но у меня есть план перехода на ASP.NET). После того, как я прочитал некоторые статьи из Интернета, есть две рамки, которые меня интересуют, MEF и Unity. Я хочу знать, что между ними реальный мир, и что хорошо делать.
Что отличает между собой и цель MEF и Unity?
Ответ 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 для частей, которые должны быть динамически расширяемыми.
Ответ 2
Есть много вариантов для выполнения DI. Прежде всего, вы должны понимать, что DI - это не инструменты, а скорее шаблоны и принципы. Вы можете использовать DI просто отлично без инструмента. Если вы это сделаете, мы назовем его Бедный человек DI.
Однако, существует много контейнеров DI, доступных для .NET. Единство - это лишь один из них.
MEF очень похож на контейнер DI, но в настоящее время решает другую проблему - проблему расширяемости. Вместо внешней конфигурации компонентов (которые используются все контейнеры DI) он использует механизм обнаружения на основе атрибутов.