在MEF中创建一个新实例

发布于 2024-12-02 09:35:01 字数 278 浏览 1 评论 0原文

我正在使用 MEF 作为插件,我创建了一个具有属性的类 PluginManager

<ImportMany()>

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

现在想要创建一个新实例,当我从插件查询时,

我已经将 PartCreationpolicy 设置为 Nonshared,但仍然不是在职的。

有什么解决办法吗?

I am using MEF for Plug-in, I made one class PluginManager which has propety

<ImportMany()>

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

Now want to create a new instance of when i query from plugins,

I have already set PartCreationpolicy as Nonshared, but still its not working.

What is solution for it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小镇女孩 2024-12-09 09:35:01

Lazy 类型(与其 Lazy 对应项一样,提供延迟实例化(例如延迟加载)。本质上,第一次 Value 属性被调用时,它会调用一个委托函数,该函数从容器中获取导出,组合它并返回其值,因此对 Value 属性的任何后续调用都将返回相同的值。对此,PartCreationPolicy 不太相关,因为尽管这在容器级别仍然很重要,但惰性实例只会保留相同的值,

您使用 GetExports 的解决方案是。确保遵守 PartCreationPolicy 的一种方法,但您必须依赖于必须将正确的 CreationPolicy 应用于该类型的事实,

您可以考虑使用工厂 。你的有两种方法可以做到这一点,您可以使用 ExportFactory 它允许您每次启动新实例(这包含在 MEF 的 Silverlight 变体中,但是 [ Glenn Block 还针对 .NET 4.0 发布了它@他的 SkyDrive - Composition.Initialization.Desktop])。

使用导出工厂,您可以将导入更改为:

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

并通过 CreateExport() 获取 ExportLifetimeContext.Value 属性返回。

另一种方法是,如果您定义另一个合约,我们将其称为 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 实例,然后通过调用工厂的 CreateInstance 方法创建您的 IPlugin 实例。您需要考虑的另一件事是,如果您的 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,您可以通过多种方法解决同一问题,您只需决定哪种方法更适合您的设计。

The Lazy<T,TMetadata> type (like its Lazy<T> counterpart provides of deferred instantiation (e.g. lazy loading). Essentially, the first time the Value property is called, it calls a delegated function which grabs the export from the container, composes it and returns its value. Any subsequent call to the Value property will return the same value. Because of this, PartCreationPolicy is less relevant, because although that still matters at the container level, the lazy instance will only hold onto the same value.

You're solution to use GetExports is one method of ensuring the PartCreationPolicy is observed, but you have to rely on the fact that the correct CreationPolicy must be applied to the type.

What you could consider is using factories instead of your plugin types. There are two ways of doing this, you could use ExportFactory<T, TMetadata> which allows you to spin up new instances each time (this is included in the Silverlight variant of MEF, but [Glenn Block also released it for .NET 4.0 @ his SkyDrive - Composition.Initialization.Desktop]).

With export factory, you could change your imports to:

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

And grab the ExportLifetimeContext<T>.Value property return through CreateExport().

The other way you could do it, is if you define another contract, let's call it IPluginFactory, which could look like:

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

(Sorry if the syntax isn't quite right, I don't usually do VB).

Now, you could change your import to be:

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

...and grab your IPluginFactory instance, then create your IPlugin instance by calling the factory's CreateInstance method. The other thing you need to consider, is that if your IPlugin instance requires composing itself (to satisfy it's own part imports), you need to compose this with your container. To that end, what might be nice, is if your export your container instance, that way you could import it via your factory constructor:

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

My preference would be to use ExportFactory itself, as you don't really have to pass around a container instance, and you get the benefits of automatic instance composition when you grab the part from the factory, but if you want absolute fine grained control over how the plugin instance is created, you can (as shown above) create quite a simple factory.

Whether or not it is right to be passing the container around is another question you'd need to ask, as it does make your factories explicitly dependent on CompositionContainer, and thus might make testing it a little more complicated.

What I hope you see, is that with MEF there are a myriad of ways you could solve the same problem, you just have to decide what fits better into your design.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文