如果我有一个类型MyClass,请注册
[Export(typeof(Myclass))]
属性和
[PartCreationPolicy(CreationPolicy.Shared)]
或
[PartCreationPolicy(CreationPolicy.NonShared)]
后来试图打电话
compositionContainer.GetExportedValue<Myclass>()
多次。
问题:通过第一次通话,我将通过MEF获取我的注册课程 - llokup所有已注册的程序集,然后尝试查找一个已注册的合同。问题是关于第二次等等 - MEF会再次进行全局查询还是在内部缓存?
答案 0 :(得分:7)
MEF会再次进行全局查找,还是在内部缓存
是的,如果您对MEF性能提出疑问,MEF会执行一些缓存并广泛使用延迟初始化:
1)缓存元数据(可组合部分,导出定义和导入定义)。例如:
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)导出的值也被缓存:
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
时,当您请求导出值时,会一次又一次地创建导出值。但即使在这种情况下,也不会执行“全局查找”,因为无论如何都会缓存元数据。
答案 1 :(得分:0)
每次使用[PartCreationPolicy(CreationPolicy.NonShared)]
时都会进行查找。然后,您必须自己实现缓存。
默认实现使用Singleton模式。这等于属性[PartCreationPolicy(CreationPolicy.Shared)]
。 这是最佳做法。
答案 2 :(得分:0)
尽管可能部分缓存了值/元数据,但进行一些性能测试表明,每次调用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<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
{
}
}
有关更多变体,请查看此要点: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倍。