Почему MEF имеет [ImportMany], а не только [Import] - PullRequest
3 голосов
/ 19 декабря 2011

Я только что нашел проблему в моем приложении mef; проблема заключалась в том, что у меня было [Import] вместо [ImportMany] в моем IEnumerable<IFoo> свойстве. Я начал задаваться вопросом, почему. MEF видит, что целью внедрения является «коллекция», и может определить, что коллекция нужна вместо одного элемента. По крайней мере, Ninject работает таким образом.

У кого-нибудь есть понимание, почему требуется [ImportMany]? Единственная причина, о которой я могу думать, это то, что кто-то может захотеть [Export(typeof(IEnumerable<IBar>)] public IEnumerable<Bar> { get; }, но действительно ли это причина такого дизайна? Могу поспорить, я не единственный, кто отлаживал такого рода ошибки.

Ответы [ 2 ]

6 голосов
/ 19 декабря 2011

Это не то же самое;)

[Import] означает, что вы хотите импортировать одну вещь в соответствии с контрактом.В MEF контракт - это просто строка, и когда вы импортируете тип (например, IEnumerable<IBar>), вы действительно импортируете в соответствии с контрактом, который является просто name этого типа.

В MEF кардинальность очень важна, поэтому, когда вы заявляете, что хотите импортировать единственный экземпляр чего-то, что соответствует указанному контракту, может быть только один источник.Если найдено несколько экспортов, возникает исключение из-за несоответствия количества элементов.

Функциональность [Import] не содержит специальной логики для обработки IEnumerable<T>, поэтому с ее точки зрения это просто контракткак и все остальное.

Атрибут [ImportMany], тем не менее, существует специально для преодоления этого разрыва.Он принимает ноль к любому количеству экспорта по указанному контракту.Это означает, что вместо одного экспорта IEnumerable<IBar> вы можете иметь много экспортов IBar, разбросанных по нескольким сборкам, и никогда не будет несоответствия количества элементов.

В конце концов, это философия дизайна.MEF мог иметь специальные встроенные знания о IEnumerable<T>.Autofac (и, по-видимому, Ninject) делает это и называет это типом отношения .

Однако подобный специальный регистр подразумевает, что где-то код реализации нарушает принцип замены Лискова , что снова может привести к нарушениям POLA , поэтому в этом случае я склонен принять сторону конструкторов MEF.Переход к более явному API может снизить вероятность обнаружения, но может быть немного безопаснее.

2 голосов
/ 20 декабря 2011

Чтобы немного упростить приведенный выше ответ:

  • [Import] сгенерирует исключение, если существует более одного совпадающего экспорта.
  • [ImportMany] загрузит более одного совпаденияэкспорт без выдачи ошибки.

Если у меня есть IDataAccessLayer, который я хочу импортировать, должен быть доступен только ОДИН экспорт - я никогда не буду писать в 2 базы данных одновременно, поэтому я использую[Import] для обеспечения существования только одного.

Если я захочу загрузить много разных BusinessObjects, я буду использовать [ImportMany], потому что я хочу много разных типов BusinessObjects.

...