2013-01-11 14 views
5

Se ho un tipo MyClass, registrarsi conLe esportazioni di MEF vengono memorizzate nella cache o rilevate ogni volta su richiesta?

[Export(typeof(Myclass))] attributo e

[PartCreationPolicy(CreationPolicy.Shared)]

o

[PartCreationPolicy(CreationPolicy.NonShared)]

e successivamente cercando di chiamare

compositionContainer.GetExportedValue<Myclass>() più volte.

Domanda: con la prima chiamata, otterrò la mia classe registrata via MEF - llokup tutte le assemblee registrate, quindi cercherò di trovare un contratto registrato. La domanda riguarda la seconda volta e così via: MEF effettuerà nuovamente la ricerca globale o memorizzerà una cache internamente?

risposta

7

sarà MEF fare ancora ricerca globale o memorizza nella cache da qualche parte internamente

Sì, MEF perfoms alcuni caching e ampiamente utilizza l'inizializzazione differita, se si mette in discussione è di circa Prestazioni MEF:

1) i metadati (parti componibili, definizioni di esportazione e definizioni di importazione) vengono memorizzati nella cache. Esempio:

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

2) esportato valori vengono memorizzati nella cache troppo:

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

Naturalmente, quando si utilizza CreationPolicy.NonShared, valore esportato viene creato ancora e ancora, quando ne facciano richiesta. Ma anche in questo caso la "ricerca globale" non viene eseguita, perché i metadati sono comunque memorizzati nella cache.

+0

Grazie per la tua spiegazione! –

+0

Questo è incompleto, nel senso che alcune ricerche vengono ancora eseguite su ogni chiamata. Quindi, fare il caching sul lato client se ci sono molte chiamate a 'GetExportedValue' dovrebbe essere fatto. –

0

Effettua una ricerca ogni volta, quando si utilizza [PartCreationPolicy(CreationPolicy.NonShared)]. Dovrai quindi implementare la cache da solo.

L'implementazione predefinita utilizza un modello Singleton. Questo è uguale all'attributo [PartCreationPolicy(CreationPolicy.Shared)]. Questa è la procedura consigliata.

Per ulteriori informazioni, leggere http://blogs.microsoft.co.il/blogs/bnaya/archive/2010/01/09/mef-for-beginner-part-creation-policy-part-6.aspx

+0

"Fa una ricerca ogni volta" - prova? – Dennis

+0

Grazie per avermi svegliato. La mia risposta era incompleta. Mi sono distratto ... – Jacco

+0

Penso che la questione non riguardi il caching del valore esportato concreto. – Dennis

0

Sebbene i valori/metadati possano essere parzialmente memorizzati nella cache, eseguire alcuni test delle prestazioni mostra che viene eseguita una ricerca ogni volta che viene effettuata una chiamata a GetExportedValue. Quindi se hai molte chiamate in cui devi ottenere il valore, dovresti fare da solo la cache.

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<ExportedClass>(); 
      } 
     } 

     private static ExportedClass cachedClass; 
     public static ExportedClass CachedClass 
     { 
      get 
      { 
       return cachedClass ?? (cachedClass = Container.GetExportedValue<ExportedClass>()); 
      } 
     } 

     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 
    { 
    } 
} 

Per ulteriori variazioni, guardare a questo succo: https://gist.github.com/DanielRose/d79f0da2ef61591176ce

Sul mio computer, Windows 7 x64, .NET 4.5.2:

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

Utilizzando MEF 2 da NuGet:

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

Nell'applicazione effettiva dove lavoro, questo fatto l'applicazione 6x più lento.

Problemi correlati