Les exportations MEF sont-elles mises en cache ou sont-elles découvertes à chaque fois sur demande?

Si j’ai un type MyClass, inscrivez-vous auprès de

[Export(typeof(Myclass))] , et

[PartCreationPolicy(CreationPolicy.Shared)]

ou

[PartCreationPolicy(CreationPolicy.NonShared)]

et plus tard en essayant d’appeler

compositionContainer.GetExportedValue() plusieurs fois.

Question: dès le premier appel, je recevrai mon cours enregistré via MEF – llokup tous les assemblées enregistrées, puis je tenterai de trouver un contrat enregistré. La question concerne la deuxième fois et ainsi de suite – le MEF effectuera-t-il une nouvelle recherche globale ou mettra-t-il en cache quelque part en interne?

MEF fera-t-il de nouveau la recherche mondiale ou mettra-t-il en cache quelque part en interne

Oui, MEF effectue une certaine mise en cache et utilise largement l’initialisation lente, si vous vous interrogez sur les performances de MEF:

1) les métadonnées (parties composables, définitions d’exportation et définitions d’importation) sont mises en cache. Exemple:

 public override IEnumerable ExportDefinitions { get { if (this._exports == null) { ExportDefinition[] exports = this._creationInfo.GetExports().ToArray(); lock (this._lock) { if (this._exports == null) { this._exports = exports; } } } return this._exports; } } 

2) les valeurs exscopes sont également mises en cache:

 public object Value { get { if (this._exportedValue == Export._EmptyValue) { object exportedValueCore = this.GetExportedValueCore(); Interlocked.CompareExchange(ref this._exportedValue, exportedValueCore, Export._EmptyValue); } return this._exportedValue; } } 

Bien sûr, lorsque vous utilisez CreationPolicy.NonShared , la valeur exscope est créée à plusieurs resockets, lorsque vous le demandez. Mais même dans ce cas, la “recherche globale” n’est pas effectuée, car les métadonnées sont de toute façon mises en cache.

Il effectue une recherche chaque fois que vous utilisez [PartCreationPolicy(CreationPolicy.NonShared)] . Vous devez ensuite implémenter vous-même la mise en cache.

L’implémentation par défaut utilise un modèle Singleton. Cela équivaut à l’atsortingbut [PartCreationPolicy(CreationPolicy.Shared)] . C’est la meilleure pratique .

Pour plus d’informations, consultez http://blogs.microsoft.co.il/blogs/bnaya/archive/2010/01/09/mef-for-beginner-part-creation-policy-part-6.aspx

Bien que les valeurs / métadonnées puissent être partiellement mises en cache, certains tests de performances montrent que certaines recherches sont effectuées chaque fois qu’un appel à GetExportedValue est effectué. Ainsi, si vous avez plusieurs appels pour lesquels vous devez obtenir la valeur, vous devez effectuer la mise en cache vous-même.

 namespace MEFCachingTest { using System; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; using System.ComponentModel.Composition.Primitives; using System.Diagnostics; using System.Reflection; public static class Program { public static CompositionContainer Container { get; set; } public static ComposablePartCatalog Catalog { get; set; } public static ExportedClass NonCachedClass { get { return Container.GetExportedValue(); } } private static ExportedClass cachedClass; public static ExportedClass CachedClass { get { return cachedClass ?? (cachedClass = Container.GetExportedValue()); } } public static void Main() { Catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly()); Container = new CompositionContainer(Catalog); const int Runs = 1000000; var stopwatch = new Stopwatch(); // Non-Cached. stopwatch.Start(); for (int i = 0; i < Runs; i++) { var ncc = NonCachedClass; } stopwatch.Stop(); Console.WriteLine("Non-Cached: Time: {0}", stopwatch.Elapsed); // Cached. stopwatch.Restart(); for (int i = 0; i < Runs; i++) { var cc = CachedClass; } stopwatch.Stop(); Console.WriteLine(" Cached: Time: {0}", stopwatch.Elapsed); } } [Export] [PartCreationPolicy(CreationPolicy.Shared)] public class ExportedClass { } } 

Pour plus de variations, regardez cet article: https://gist.github.com/DanielRose/d79f0da2ef61591176ce

Sur mon ordinateur, Windows 7 x64, .NET 4.5.2:

 Non-Cached: Time: 00:00:02.1217811 Cached: Time: 00:00:00.0063479 

Utilisation de MEF 2 de NuGet:

 Non-Cached: Time: 00:00:00.2037812 Cached: Time: 00:00:00.0023358 

Dans l'application réelle où je travaille, l'application était 6x plus lente.