Я был очень удивлен, получив эту ошибку сегодня, поскольку с ней я никогда не сталкивался раньше. Все в коде выглядело нормально, поэтому я провел несколько поисков. Предыдущие вопросы и соответствующие ответы не помогли.
Этот был решен, когда автор убедился, что ссылки на его сборку были последовательными У меня сейчас нет этой проблемы, потому что я сейчас ссылаюсь на другой проект в своем решении.
Этот был решен, когда постеру было приказано использовать ImportMany, но я уже использую его (я тоже думаю, что правильно), чтобы попытаться загрузить несколько плагинов
Это было решено, когда автор понял, что было несоответствие цели платформы. Я уже просмотрел свои проекты, чтобы убедиться, что все нацелено на x86.
Так вот что я пытаюсь сделать. У меня есть плагин, который владеет подключением к устройству. Мне также может понадобиться поделиться этим подключением с другим плагином. Я решил, что самый простой способ сделать это - создать интерфейс, который позволял бы подключаемому плагину запрашивать собственное соединение с устройством. Давайте просто назовем это IConnectionSharer
. Если подключаемому плагину не необходимо заимствовать это соединение и он имеет свое собственное, то для подключения к устройству он должен использовать собственную реализацию IConnectionSharer
.
Мой плагин "master" (тот, который владеет подключением к устройству) реализует IConnectionSharer
. Это также экспортирует это через ExportAttribute.
Моя сборка плагина "slave" определяет класс, который также реализует и экспортирует IConnectionSharer
.
Когда приложение загружается, цель заключается в том, чтобы мой плагин slave через MEF перечислил все IConnectionSharer
s и сохранил их в IEnumerable<IConnectionSharer>
. Это так:
[ImportMany]
public IEnumerable<IConnectionSharer> AllSharedConnections { get; set; }
Николай попросил меня показать мои Export
с, так что вот они.
Плагин "Мастер":
[PartCreationPolicy(CreationPolicy.Shared)]
[Export(typeof(Interface1))]
[Export(typeof(Interface2))]
[Export(typeof(Interface3))]
[Export(typeof(IConnectionSharer))]
public partial class MasterPlugin : Interface1, Interface2, Interface3, IConnectionSharer
{
...
}
Плагин "Slave":
[PartCreationPolicy(CreationPolicy.Shared)]
[Export(typeof(Interface1))]
public class SlavePlugin : Interface1
{
private Model _model { get; set; }
private ViewModel _viewmodel { get; set; }
[ImportingConstructor]
public SlavePlugin( [Import] Model model)
{
_model = model;
_viewmodel = new ViewModel( model);
}
}
Модель:
[Export(typeof(Model))]
public class Model
{
[ImportMany(typeof(IConnectionSharer))]
private IEnumerable<IConnectionSharer> AllSharedConnections { get; set; }
...
}
Внутренняя реализация IConnectionSharer для плагина "slave":
[Export(typeof(IConnectionSharer))]
public class PrivateConnection : IConnectionSharer
{
...
}
Но во время компоновки детали я получаю ошибку при экспорте 'Company. MasterPlugin (ContractName = "IConnectionSharer") "нельзя назначить типу' IConnectionSharer '.
Само сообщение об ошибке кажется достаточно ясным - как будто MEF считает, что мой мастер-плагин не наследует от IConnectionSharer ... но это так! Кто-нибудь может предложить дальнейшие стратегии отладки? Я собираюсь начать болезненный процесс одиночного перехода через источник MEF.
UPDATE
Это интересная подсказка - если после очистки моей выходной папки и перестроения решения я удалю плагин "master" (так что плагин "slave" будет использовать свой собственный объект IConnectionSharer ), мое приложение загружается просто отлично, и мой подчиненный плагин также ведет себя как ожидалось. Если я помещаю основной плагин обратно в папку плагинов, у меня снова возникает проблема с композицией MEF.
Я также подумал, что попробую использовать Lazy <>, чтобы посмотреть, будет ли это иметь эффект. Результат был немного поразительным. MEF жалуется на эту ошибку: Невозможно заполнить коллекцию AllSharedConnections, поскольку она не реализует ICollection или доступна только для чтения. Если коллекция не IEnumerable<T>
или T [], она должна реализовывать ICollection и быть либо предварительно инициализированной, либо быть доступной для записи с помощью конструктора по умолчанию.
HUH? Очевидно, что AllSharedConnections равно и IEnumerable<T>
, так почему MEF жалуется?