2016-07-04 32 views
5

Gibt es eine Möglichkeit zum Zwischenspeichern von MEF-Komponenten Graphen pro Anwendung Start (WPF), wie die MAF tun, um zu vermeiden, die Verzeichnisse und Konstruieren der Komponenten Diagramm jeder Anwendung Start. um den Start meiner Anwendung zu beschleunigen. MAF verwendet AddinsStore zum Speichern aller Add-Ins, wenn das neue Add-In den Store neu erstellt und erneut gespeichert hat. ist es möglich, dies mit Modular-Anwendung mit MEF zu tun?Caching MEF-Komponenten

EDIT:

in meinem Projekt Architektur Ich habe Extension Module und den Managed Service So ich habe verschiedene Exporte wie (IExtension, IModule, IManagedService) und i Umgang mit dem Start Abhängigkeiten aller Komponenten, was ich will genau ex (Das Extensions Directory) enthält viele dlls und es kann sein, dass nicht alle dlls ein (exports/Imports) enthalten, da einige der dlls nur auf einige Extensions verweisen. Das Standard-Erkennungsverhalten von MEF sucht also nach Exporten/Importen in allen Assemblies im Extension Directory, aber ich möchte dieses Verhalten ändern, indem ich zuerst alle dlls ansehe und die Typen und deren Namen und DLLs abfange, um sie zu verwenden die nächste Startzeit. vom Fang direkt laden Komponenten (Exporte), so dass die MEF wird die verfügbaren Komponenten und ihre Plätze kennen, ohne die DLLs zu laden und zu durchsuchen. Es scheint wie ein Wörterbuch von Exporten und deren Orten und Abhängigkeiten zu sein, um die Instanz direkt von ihren Orten (dll) zu bekommen.

+0

Ich verstehe diese Frage nicht ... Ich habe noch nie MAF gemacht, aber viel MEF.Warum verschiebst du einfach alle MEF-Komponenten in den gleichen Ordner und lädst sie direkt von dort? Nach dem Lesen von [this] (http://stackoverflow.com/questions/835182/choosing-between-mef-and-maf-system-addin), scheint MAF wie eine unnötige komplizierte Möglichkeit, Dinge zu erledigen – lokusking

+0

Nein, ich kann nicht Verschiebe alle Assemblies in ein Verzeichnis. Ich benutze Verzeichniskataloge und ich habe die fließende Struktur: (Erweiterungen, Module, Managed Services, SDK) Ordner, der Ladeauftrag wichtig. –

+0

Sie können die Load-Order auch in Mef einstellen. Es erfordert etwas hässlichen Code, aber es funktioniert. Wenn Sie daran interessiert sind, wie zu, lassen Sie es mich wissen, und ich werde eine Antwort posten – lokusking

Antwort

1

Ich weiß nicht, ob dies Ihnen um 100% helfen wird, aber mit diesem Code, der die Ladereihenfolge meiner Module steuert.

Wenn Sie Ihre Last Ordnung steuern können, können Sie in der Lage sein, alle im selben Ordner, um Ihre * .dll zu setzen und etwas Zeit zu sparen, so dass sie in Unterordner zu finden:

Der Schlüssel dazu ist die Verwendung von dieses zusätzliche Attribut: [ExportMetadata("Order", 1)]

Dann wird Ihr Plugin sollte wie folgt aussehen:

[Export(typeof(YourContract))] 
    [ExportMetadata("Order", 1)] 
    public class YourPlugin: YourContract{} 

Dinge in der richtigen Reihenfolge geladen zu bekommen, werden Sie so etwas wie dieses benötigen:

Schnittstelle:

public interface IOrderMetadata { 
    [DefaultValue(int.MaxValue)] 
    int Order { 
     get; 
    } 
    } 

AdaptingCollection:

public class AdaptingCollection<T, M> : ICollection<Lazy<T, M>>, INotifyCollectionChanged { 
    /// <summary> 
    /// Constructor</summary> 
    public AdaptingCollection() 
     : this(null) { 
    } 

    /// <summary> 
    /// Constructor</summary> 
    /// <param name="adaptor">Function to apply to items in the collection</param> 
    public AdaptingCollection(Func<IEnumerable<Lazy<T, M>>, IEnumerable<Lazy<T, M>>> adaptor) { 
     this._mAdaptor = adaptor; 
    } 

    /// <summary> 
    /// CollectionChanged event for INotifyCollectionChanged</summary> 
    public event NotifyCollectionChangedEventHandler CollectionChanged; 

    /// <summary> 
    /// Force the adaptor function to be run again</summary> 
    public void ReapplyAdaptor() { 
     if (this._mAdaptedItems == null) return; 
     this._mAdaptedItems = null; 
     this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 
    } 

    #region ICollection Implementation 

    /// <summary> 
    /// Returns whether the item is present in the collection</summary> 
    /// <remarks>Accessors work directly against adapted collection</remarks> 
    /// <param name="item">Item to look for</param> 
    /// <returns>True if the item is in the collection</returns> 
    public bool Contains(Lazy<T, M> item) { 
     return this.AdaptedItems.Contains(item); 
    } 

    /// <summary> 
    /// Copies the entire list to a one-dimensional array, starting at the specified index of the target array</summary> 
    /// <remarks>Accessors work directly against adapted collection</remarks> 
    /// <param name="array">The target array</param> 
    /// <param name="arrayIndex">The starting index</param> 
    public void CopyTo(Lazy<T, M>[] array, int arrayIndex) { 
     this.AdaptedItems.CopyTo(array, arrayIndex); 
    } 

    /// <summary> 
    /// Gets the number of items in the collection</summary> 
    /// <remarks>Accessors work directly against adapted collection</remarks> 
    public int Count => this.AdaptedItems.Count; 

    /// <summary> 
    /// Gets whether the collection is read only.</summary> 
    /// <remarks>Accessors work directly against adapted collection</remarks> 
    public bool IsReadOnly => false; 

    /// <summary> 
    /// Gets an enumerator for the collection</summary> 
    /// <remarks>Accessors work directly against adapted collection</remarks> 
    /// <returns>The IEnumerator</returns> 
    public IEnumerator<Lazy<T, M>> GetEnumerator() { 
     return this.AdaptedItems.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() { 
     return this.GetEnumerator(); 
    } 

    /// <summary> 
    /// Add an item to the collection</summary> 
    /// <remarks>Mutation methods work against complete collection and then force 
    /// a reset of the adapted collection</remarks> 
    /// <param name="item">The item to add</param> 
    public void Add(Lazy<T, M> item) { 
     this._mAllItems.Add(item); 
     this.ReapplyAdaptor(); 
    } 

    /// <summary> 
    /// Clear all items from the collection</summary> 
    /// <remarks>Mutation methods work against complete collection and then force 
    /// a reset of the adapted collection</remarks> 
    public void Clear() { 
     this._mAllItems.Clear(); 
     this.ReapplyAdaptor(); 
    } 

    /// <summary> 
    /// Remove an item from the collection</summary> 
    /// <remarks>Mutation methods work against complete collection and then force 
    /// a reset of the adapted collection</remarks> 
    /// <param name="item">The item to remove</param> 
    /// <returns>True if the item was found, otherwise false</returns> 
    public bool Remove(Lazy<T, M> item) { 
     bool removed = this._mAllItems.Remove(item); 
     this.ReapplyAdaptor(); 
     return removed; 
    } 

    #endregion 

    /// <summary> 
    /// Invoke the adaptor function on the collection</summary> 
    /// <param name="collection">The collection to adapt</param> 
    /// <returns>The adapted collection</returns> 
    protected virtual IEnumerable<Lazy<T, M>> Adapt(IEnumerable<Lazy<T, M>> collection) { 
     if (this._mAdaptor != null) { 
     return this._mAdaptor.Invoke(collection); 
     } 

     return collection; 
    } 

    /// <summary> 
    /// Fire the CollectionChanged event</summary> 
    /// <param name="e">Event args</param> 
    protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { 
     this.CollectionChanged?.Invoke(this, e); 
    } 

    private List<Lazy<T, M>> AdaptedItems => this._mAdaptedItems ?? (this._mAdaptedItems = this.Adapt(this._mAllItems).ToList()); 

    private readonly List<Lazy<T, M>> _mAllItems = new List<Lazy<T, M>>(); 
    private readonly Func<IEnumerable<Lazy<T, M>>, IEnumerable<Lazy<T, M>>> _mAdaptor; 
    private List<Lazy<T, M>> _mAdaptedItems; 

    } 

OderingCollection

public class OrderingCollection<T, M> : AdaptingCollection<T, M> { 
    /// <summary> 
    /// Constructor</summary> 
    /// <param name="keySelector">Key selector function</param> 
    /// <param name="descending">True to sort in descending order</param> 
    public OrderingCollection(Func<Lazy<T, M>, object> keySelector, bool descending = false) 
     : base(e => descending ? e.OrderByDescending(keySelector) : e.OrderBy(keySelector)) { 
    } 
    } 

Nutzungs

[ImportMany(typeof(YourContract), AllowRecomposition = true)] 
    internal OrderingCollection<YourContract, IOrderMetadata> Plugins{ 
     get; private set; 
    } 

In Ihrem Constructor:

this.Plugins= new OrderingCollection<ITemplateMapper, IOrderMetadata>(
          lazyRule => lazyRule.Metadata.Order); 

Mein Laden-Code (kann von Ihnen unterscheiden):

private void LoadModules() { 
     var aggregateCatalog = new AggregateCatalog(); 
     aggregateCatalog.Catalogs.Add(new DirectoryCatalog(".", "*.Plugin.*.dll")); 
     var container = new CompositionContainer(aggregateCatalog); 
     container.ComposeParts(this);  
    } 

mir diese Hoffnung können Sie von MAF Hilfe bekommen zu befreien

+0

Es ist eine gute Idee, aber hat mir nicht geholfen, meine Ziele zu erreichen. Ich habe mehr Beschreibung in meine Frage eingefügt. Guck mal. –

+0

Entsprechend Ihrer Bearbeitung könnten Sie eine kleine Datenbank einrichten, die die installierten Plugins und deren Pfade enthält. Danach sollten Sie in der Lage sein, sie direkt zu laden, ohne Ihre Ordner zu crawlen. – lokusking

+0

Bin ich richtig, wenn ich sagte: MEF beim Erstellen eines Teils wird es versuchen, seine Importe und Exporte und Abhängigkeiten zu suchen, dann wird es die Instanz erstellen? –