Тип 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 существует множество способов решить ту же проблему, вам просто нужно решить, что лучше вписывается в ваш дизайн.