Создать новый экземпляр в MEF - PullRequest
1 голос
/ 29 августа 2011

Я использую MEF для плагина, я создал один класс PluginManager, который имеет пропет

<ImportMany()>

Public Property Plugins() As Lazy(Of IPlugin, IPluginExport)()  

Теперь хочу создать новый экземпляр запроса на плагины,

Я уже установил PartCreationpolicy как Nonshared, но он все еще не работает.

Какое решение для этого?

1 Ответ

1 голос
/ 29 августа 2011

Тип Lazy<T,TMetadata> (как и его аналог Lazy<T> обеспечивает отложенную реализацию (например, отложенную загрузку). По сути, при первом вызове свойства Value он вызывает делегированную функцию, которая захватывает экспорт из контейнера. , создает его и возвращает его значение. Любой последующий вызов свойства Value вернет то же значение. Из-за этого PartCreationPolicy менее актуален, поскольку, хотя это все еще имеет значение на уровне контейнера, ленивый экземпляр будет содержать только на то же значение.

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

То, что вы могли бы рассмотреть, это использовать фабрики вместо типов ваших плагинов. Есть два способа сделать это, вы можете использовать ExportFactory<T, TMetadata>, который позволяет вам каждый раз раскручивать новые экземпляры (это включено в вариант Silverlight MEF, но [Блок Гленна также выпустил его для .NET 4.0 @). его SkyDrive - Состав. Инициализация. Рабочий стол ]).

С фабрикой экспорта вы можете изменить свой импорт на:

<ImportMany()>
Public Property PluginFactories() As ExportFactory(Of IPlugin, IPluginExport)()

И получите возврат свойства ExportLifetimeContext<T>.Value через CreateExport().

Другой способ сделать это - определить другой контракт, назовем его IPluginFactory, который может выглядеть следующим образом:

Public Interface IPluginFactory

  Function CreateInstance() As IPlugin

End Interface

<Export(GetType(IPluginFactory))>
Public Class TestPluginFactory Implements IPluginFactory

  Public Function CreateInstance() As IPlugin 
    Implements IPluginFactory.CreateInstance

    Return New TestPlugin()
  End Function

End Class

(Извините, если синтаксис не совсем правильный, я обычно не делаю VB).

Теперь вы можете изменить свой импорт на:

<ImportMany()>
Pulic Property PluginFactories(Of IPlugin, IPluginExport)()

... и захватите свой экземпляр IPluginFactory, затем создайте свой экземпляр IPlugin, вызвав фабричный метод CreateInstance. Еще одна вещь, которую вы должны учитывать, это то, что если ваш экземпляр IPlugin требует компоновки себя (для удовлетворения импорта своих собственных деталей), вы должны скомпоновать это с вашим контейнером. Для этого может быть неплохо, если вы экспортируете экземпляр своего контейнера, то вы можете импортировать его через конструктор фабрики:

Dim container As New CompositionContainer(....)
AttributedModelServices.ComposeExportedValue(container, container)

<Export(GetType(IPluginFactory))>
Public Class TestPluginFactory Implements IPluginFactory

  Private _container As CompositionContainer

  <ImportingConstructor()>
  Public Sub New(container As CompositionContainer)
      _container = container
  End Sub

  Public Function CreateInstance() As IPlugin
    Implements IPluginFactory.CreateInstance

    Dim instance As New TestPlugin()
    AttributedModelServices.ComposeParts(_container, instance)

    Return instance
  End Function

End Class

Я бы предпочел использовать сам ExportFactory, поскольку вам на самом деле не нужно передавать экземпляр контейнера, и вы получаете преимущества автоматической компоновки экземпляра при получении детали с завода, но если вы хотите Абсолютно точный контроль над тем, как создается экземпляр плагина, вы можете (как показано выше) создать довольно простую фабрику.

Правильно ли передавать контейнер вокруг - это еще один вопрос, который вам нужно задать, поскольку это делает ваши фабрики явно зависимыми от CompositionContainer, и, следовательно, может сделать его тестирование немного более сложным.

Я надеюсь, что вы видите, что с помощью MEF существует множество способов решить ту же проблему, вам просто нужно решить, что лучше вписывается в ваш дизайн.

...