6

如果我有一种类型的 MyClass,请注册

[Export(typeof(Myclass))] 属性,和

[PartCreationPolicy(CreationPolicy.Shared)]

或者

[PartCreationPolicy(CreationPolicy.NonShared)]

后来试图打电话

compositionContainer.GetExportedValue<Myclass>()多次。

问题:第一次调用时,我将通过 MEF 获取我的注册课程 - 查找所有已注册的程序集,然后尝试找到一个已注册的合同。问题是关于第二次等等 - MEF 会再次进行全局查找还是在内部某个地方缓存?

4

3 回答 3

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,导出的值会在您请求时一次又一次地创建。但即使在这种情况下,也不会执行“全局查找”,因为元数据无论如何都会被缓存。

于 2013-01-11T09:36:31.253 回答
0

每次使用时都会进行查找[PartCreationPolicy(CreationPolicy.NonShared)]。然后,您必须自己实现缓存。

默认实现是使用单例模式。这等于属性[PartCreationPolicy(CreationPolicy.Shared)]这是最佳做法

有关更多信息,请阅读http://blogs.microsoft.co.il/blogs/bnaya/archive/2010/01/09/mef-for-beginner-part-creation-policy-part-6.aspx

于 2013-01-11T08:48:09.527 回答
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 倍。

于 2014-12-12T14:21:03.307 回答