MEF Component Caching

Is there a way to cache the graphs of the MEF components to run each application (WPF), for example, MAF, to avoid directory discovery and component graphing every time the application starts. to speed up the launch of my application. MAF uses AddinsStore to store all add-ons when a new addin displays the Store, restored and saved again. can this be done with a modular application developed using MEF?

EDIT:

in my project architecture I have an extension, modules, and managed services. I have different export resources (IExtension, IModule, IManagedService), and I process the initial dependencies of all components, that I want ex (The Extensions Directory) to contain a lot of DLLs, and maybe not all dlls contain (export / Imports), because that some of the dlls just reference some extensions. therefore, the default detection behavior of MEF is looking for export / import in all assemblies in the extension directory, but I want to change this behavior by looking at all DLLs for the first time and catching the types and their names and libraries so that they can be used at the next launch time. from the download components directly to the download (Export), so MEF will know the available components and their places without downloading and searching for DLLs. it looks like a dictionary of Exports and their places and dependencies to get an instance directly from its places (dll).

+5
source share
1 answer

I don't know if this will help you 100%, but with this code im controls the loading of my modules.

If you can control your download order, you can put all of your * .dll in the same folder and save some time by finding them in subfolders:

The key to this is to use this additional attribute: [ExportMetadata("Order", 1)]

Then your plugin should look like this:

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

To get things loaded in the correct order, you will need something like this:

Interface:

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

Using

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

In your constructor:

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

My boot code (may be different from yours):

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

Hope this helps you get rid of MAF

+1
source

All Articles