2011-08-29 5 views
1

J'utilise MEF pour Plug-in, je fait une classe PluginManager qui a propetyCréer une nouvelle instance dans le MEF

<ImportMany()> 

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

veulent maintenant créer une nouvelle instance quand je fais une recherche de plug-ins,

J'ai déjà défini PartCreationpolicy comme Non partagé, mais cela ne fonctionne toujours pas.

Quelle est la solution pour cela?

+0

J'ai trouvé une solution pour cela, Dans la fonction GetPlugin (Name), j'ai de nouveau défini la valeur des Plugins. Plugins = Container.GetExports (Of T, TMetadata). Maintenant, je reçois une nouvelle instance à chaque fois. –

Répondre

1

Le type Lazy<T,TMetadata> (comme son homologue Lazy<T> fournit des instanciation différée (par exemple le chargement paresseux). Pour l'essentiel, la première fois que la propriété Value est appelée, elle appelle une fonction déléguée qui saisit l'exportation du conteneur, Compose et retours sa valeur.Tout appel ultérieur à la propriété Value retournera la même valeur.Pour cette raison, PartCreationPolicy est moins pertinent, car même si cela importe toujours au niveau du conteneur, l'instance paresseuse ne conservera que la même valeur

Vous êtes la solution à utiliser GetExports est une méthode pour assurer le PartCreationPolicy est observé, mais vous devez compter sur le fait que le CreationPolicy correct doit être appliqué au type.

Ce que vous pourriez envisager est d'utiliser des usines au lieu de vos types de plugins. Il y a deux façons de le faire, vous pouvez utiliser ExportFactory<T, TMetadata> qui vous permet de lancer de nouvelles instances à chaque fois (ceci est inclus dans la variante Silverlight de MEF, mais [Glenn Block l'a également publié pour .NET 4.0 @ his SkyDrive - Composition.Initialization.Desktop]).

Avec l'usine d'exportation, vous pouvez changer vos importations:

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

Et prenez le retour de la propriété ExportLifetimeContext<T>.Value par CreateExport().

L'autre façon, vous pouvez le faire, est de savoir si vous définissez un autre contrat, nous allons l'appeler IPluginFactory, ce qui pourrait ressembler à:

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 

(Désolé si la syntaxe est pas tout à fait raison, je n » t habituellement faire VB).

Maintenant, vous pouvez changer votre importation être:

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

... et prenez votre instance IPluginFactory, créez votre IPlugin exemple en appelant la méthode de l'usine CreateInstance. L'autre chose que vous devez considérer est que si votre instance IPlugin nécessite de se composer elle-même (pour satisfaire ses propres importations), vous devez le composer avec votre conteneur. À cette fin, ce qui pourrait être agréable, est si votre exportation de votre instance de conteneur, de cette façon, vous pouvez l'importer via votre constructeur d'usine:

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 

Ma préférence serait d'utiliser lui-même ExportFactory, comme vous le faites pas vraiment avoir à passer par une instance de conteneur, et vous bénéficiez des avantages de la composition automatique des instances lorsque vous récupérez la pièce en usine, mais si vous voulez un contrôle précis de la création de l'instance de plugin, vous pouvez (comme illustré ci-dessus) créer une usine assez simple.

Que vous ayez à passer le conteneur ou non, c'est une autre question que vous devez poser, car cela rend vos usines explicitement dépendantes de CompositionContainer, et peut donc rendre le test un peu plus compliqué. Ce que j'espère que vous voyez, c'est qu'avec MEF, il existe une myriade de façons de résoudre le même problème, il vous suffit de décider ce qui convient le mieux à votre conception.

Questions connexes