是否每次都要求MEF导出缓存或发现?
如果我有一个类型MyClass,请注册
[Export(typeof(Myclass))]
属性,和
[PartCreationPolicy(CreationPolicy.Shared)]
要么
[PartCreationPolicy(CreationPolicy.NonShared)]
然后试着打电话
compositionContainer.GetExportedValue()
多次。
问题:在第一次通话时,我将通过MEF获取我的注册课程 – llokup所有已注册的程序集,然后尝试查找一个已注册的合同。 问题是关于第二次等等 – MEF会再次进行全局查询还是在内部缓存?
MEF会再次进行全局查找,还是在内部缓存
是的,如果您对MEF性能有疑问,MEF会执行一些缓存并广泛使用延迟初始化:
1)缓存元数据(可组合部分,导出定义和导入定义)。 例:
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)导出的值也被缓存:
public object Value { get { if (this._exportedValue == Export._EmptyValue) { object exportedValueCore = this.GetExportedValueCore(); Interlocked.CompareExchange(ref this._exportedValue, exportedValueCore, Export._EmptyValue); } return this._exportedValue; } }
当然,在使用CreationPolicy.NonShared
时,当您请求时,会一次又一次地创建导出的值。 但即使在这种情况下,也不会执行“全局查找”,因为无论如何都会缓存元数据。
当您使用[PartCreationPolicy(CreationPolicy.NonShared)]
时,它每次都进行查找。 然后,您必须自己实现缓存。
默认实现使用Singleton模式。 这等于属性[PartCreationPolicy(CreationPolicy.Shared)]
。 这是最好的做法 。
有关更多信息,请参阅http://blogs.microsoft.co.il/blogs/bnaya/archive/2010/01/09/mef-for-beginner-part-creation-policy-part-6.aspx
尽管可以部分缓存值/元数据,但执行某些性能测试表明,每次调用GetExportedValue
时都会执行一些查找。 因此,如果您需要获取值的许多调用,您应该自己进行缓存。
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 { } }
有关更多变化,请查看以下要点: https : //gist.github.com/DanielRose/d79f0da2ef61591176ce
在我的计算机上,Windows 7 x64,.NET 4.5.2:
Non-Cached: Time: 00:00:02.1217811 Cached: Time: 00:00:00.0063479
使用NuGet的MEF 2:
Non-Cached: Time: 00:00:00.2037812 Cached: Time: 00:00:00.0023358
在我工作的实际应用程序中,这使应用程序速度降低了6倍。