Are MEF exports cached or discovering every time on request?

前端 未结 3 1364
伪装坚强ぢ
伪装坚强ぢ 2021-01-05 16:23

If I have one type MyClass, register with

[Export(typeof(Myclass))] attribute, and

[PartCreationPolicy(CreationPolicy.Shared)]

3条回答
  •  [愿得一人]
    2021-01-05 16:47

    Although the values/metadata might be partially cached, doing some performance testing shows that some lookup is performed every time a call to GetExportedValue is made. So if you have many calls where you need to get the value, you should do the caching yourself.

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

    For more variations, look at this gist: https://gist.github.com/DanielRose/d79f0da2ef61591176ce

    On my computer, Windows 7 x64, .NET 4.5.2:

    Non-Cached: Time: 00:00:02.1217811
        Cached: Time: 00:00:00.0063479
    

    Using MEF 2 from NuGet:

    Non-Cached: Time: 00:00:00.2037812
        Cached: Time: 00:00:00.0023358
    

    In the actual application where I work, this made the application 6x slower.

提交回复
热议问题