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.