2016-07-04 6 views
5

MAFのようにMEFコンポーネントのグラフをキャッシュする方法はありますか(MAFのように)、アプリケーションの起動時にコンポーネントのグラフを作成し、ディレクトリを検出しないようにします。私のアプリケーションの起動をスピードアップするために。 MAFは、新しいアドインがストアを再構築して再度保存すると、AddinsStoreを使用してすべてのアドインを格納します。それはMEFで設計されたモジュラーアプリケーションで行うことが可能ですか?MEFコンポーネントをキャッシュする

EDIT:私のプロジェクトの建築で

私は拡張、モジュールおよびマネージドサービスを持っているので、私は(IExtension、はIModule、IManagedService)のような別の輸出を持っている、と私はすべてのコンポーネントの開始の依存関係を処理し、どのような私は正確にex(The Extensions Directory)にはたくさんのdllが含まれていて、dllの中にはいくつかの拡張機能を参照するものがあるため、すべてのdllに(exports/Imports)が含まれているわけではありません。したがって、MEFのデフォルトの検出動作は、拡張ディレクトリ内のすべてのアセンブリのエクスポート/インポートを検索していますが、最初にすべてのDLLを調べ、タイプとその名前とDLLを使用してこの動作を変更します次の起動時間。キャッチから直接コンポーネント(エクスポート)をロードするので、MEFはdllをロードしたり検索したりすることなく、利用可能なコンポーネントとその場所を知ることができます。その場所(dll)から直接インスタンスを取得するために、エクスポートとその場所と依存関係の辞書のように見えます。

+0

を取り除くためにあなたを助けるかもしれない願っています私はその質問を理解していません...前にMAFをやったことはありませんが、MEFはたくさんあります。なぜあなたは単純にすべてのMEFコンポーネントを同じフォルダに移動し、そこから直接ロードするのですか? [この](http://stackoverflow.com/questions/835182/choosing-between-mef-and-maf-system-addin)を読んだ後、MAFは物事を完了させるために不要な複雑な方法のように思えます。 – lokusking

+0

いいえ、私はできません。すべてのアセンブリを1つのディレクトリに移動します。私はディレクトリカタログを使用しており、私は流れる構造を持っています:(拡張モジュール、管理サービス、SDK)フォルダ、読み込み順序が重要です。 –

+0

Mefでもロード・オーダーを設定できます。これは、醜いコードのビットが必要ですが、それは動作します。あなたがこの方法に興味があるなら、私に知らせて、私は答えを投稿します – lokusking

答えて

1

これが100%助けになるかどうかは分かりませんが、このコードではモジュールの読み込み順序を制御しています。

あなたは、負荷の順序を制御することができた場合、あなたがサブフォルダにそれらを見つけ、いくつかの時間を同じフォルダにすべての*の.dllのを入れて保存することができるかもしれない:

これの鍵は、の使用でありますこの追加属性:[ExportMetadata("Order", 1)]

次に、あなたのプラグインは次のようになります。

0:

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

物事が正しい順序でロード取得することを、あなたはこのようなものが必要になります

インタフェース:

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

使用

あなたのコンストラクタで
[ImportMany(typeof(YourContract), AllowRecomposition = true)] 
    internal OrderingCollection<YourContract, IOrderMetadata> Plugins{ 
     get; private set; 
    } 

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

マイロード・コード(あなたと異なる場合があります):

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

私は、これはMAF

+0

それは良いアイデアですが、私の目標を達成するのに役立たなかった。私は私の質問に詳しい説明を追加しました。見てみましょう。 –

+0

あなたの編集によれば、インストールされたプラグインとそのパスを含む小さなデータベースをセットアップできます。その後、フォルダをクロールせずに直接ロードできるはずです。 – lokusking

+0

私はそう言っています:MEFパートを作成するときに、インポートとエクスポートと依存関係を検索しようとすると、インスタンスが作成されますか? –

関連する問題