Browse Source

Use generics trick to cache tag helper instances (#28208)

- Remove the use of ITypeActivatorCache
David Fowler 5 years ago
parent
commit
27610b0901

+ 9 - 20
src/Mvc/Mvc.Razor/src/Infrastructure/DefaultTagHelperActivator.cs

@@ -2,9 +2,9 @@
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 
 using System;
-using Microsoft.AspNetCore.Mvc.Infrastructure;
 using Microsoft.AspNetCore.Mvc.Rendering;
 using Microsoft.AspNetCore.Razor.TagHelpers;
+using Microsoft.Extensions.DependencyInjection;
 
 namespace Microsoft.AspNetCore.Mvc.Razor.Infrastructure
 {
@@ -13,22 +13,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Infrastructure
     /// </summary>
     internal class DefaultTagHelperActivator : ITagHelperActivator
     {
-        private readonly ITypeActivatorCache _typeActivatorCache;
-
-        /// <summary>
-        /// Instantiates a new <see cref="DefaultTagHelperActivator"/> instance.
-        /// </summary>
-        /// <param name="typeActivatorCache">The <see cref="ITypeActivatorCache"/>.</param>
-        public DefaultTagHelperActivator(ITypeActivatorCache typeActivatorCache)
-        {
-            if (typeActivatorCache == null)
-            {
-                throw new ArgumentNullException(nameof(typeActivatorCache));
-            }
-
-            _typeActivatorCache = typeActivatorCache;
-        }
-
         /// <inheritdoc />
         public TTagHelper Create<TTagHelper>(ViewContext context)
             where TTagHelper : ITagHelper
@@ -38,9 +22,14 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Infrastructure
                 throw new ArgumentNullException(nameof(context));
             }
 
-            return _typeActivatorCache.CreateInstance<TTagHelper>(
-                context.HttpContext.RequestServices,
-                typeof(TTagHelper));
+            return Cache<TTagHelper>.Create(context.HttpContext.RequestServices);
+        }
+
+        private static class Cache<TTagHelper>
+        {
+            private static readonly ObjectFactory _objectFactory = ActivatorUtilities.CreateFactory(typeof(TTagHelper), Type.EmptyTypes);
+
+            public static TTagHelper Create(IServiceProvider serviceProvider) => (TTagHelper)_objectFactory(serviceProvider, arguments: null);
         }
     }
 }

+ 1 - 2
src/Mvc/Mvc.Razor/test/Infrastructure/DefaultTagHelperActivatorTest.cs

@@ -4,7 +4,6 @@
 using System.IO;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc.Abstractions;
-using Microsoft.AspNetCore.Mvc.Infrastructure;
 using Microsoft.AspNetCore.Mvc.ModelBinding;
 using Microsoft.AspNetCore.Mvc.Rendering;
 using Microsoft.AspNetCore.Mvc.ViewEngines;
@@ -30,7 +29,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Infrastructure
             var viewContext = MakeViewContext(httpContext);
             var viewDataValue = new object();
             viewContext.ViewData.Add("TestData", viewDataValue);
-            var activator = new DefaultTagHelperActivator(new TypeActivatorCache());
+            var activator = new DefaultTagHelperActivator();
 
             // Act
             var helper = activator.Create<TestTagHelper>(viewContext);

+ 1 - 4
src/Mvc/Mvc.Razor/test/RazorPageCreateTagHelperTest.cs

@@ -82,8 +82,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
                 modelExpressionProvider);
 
             var serviceProvider = new Mock<IServiceProvider>();
-            var typeActivator = new TypeActivatorCache();
-            var tagHelperActivator = new DefaultTagHelperActivator(typeActivator);
+            var tagHelperActivator = new DefaultTagHelperActivator();
             var myService = new MyService();
             serviceProvider.Setup(mock => mock.GetService(typeof(MyService)))
                            .Returns(myService);
@@ -91,8 +90,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor
                 .Returns(new DefaultTagHelperFactory(tagHelperActivator));
             serviceProvider.Setup(mock => mock.GetService(typeof(ITagHelperActivator)))
                            .Returns(tagHelperActivator);
-            serviceProvider.Setup(mock => mock.GetService(typeof(ITypeActivatorCache)))
-                           .Returns(typeActivator);
             serviceProvider.Setup(mock => mock.GetService(It.Is<Type>(serviceType =>
                 serviceType.IsGenericType && serviceType.GetGenericTypeDefinition() == typeof(IEnumerable<>))))
                 .Returns<Type>(serviceType =>

+ 3 - 4
src/Mvc/Mvc.TagHelpers/test/DefaultTagHelperActivatorTest.cs

@@ -1,10 +1,9 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// Copyright (c) .NET Foundation. All rights reserved.
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 
 using System.Text.Encodings.Web;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Mvc.Infrastructure;
 using Microsoft.AspNetCore.Mvc.Razor.Infrastructure;
 using Microsoft.AspNetCore.Mvc.Rendering;
 using Microsoft.AspNetCore.Mvc.Routing;
@@ -29,7 +28,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
         public void ScriptTagHelper_DoesNotUseMemoryCacheInstanceFromDI()
         {
             // Arrange
-            var activator = new DefaultTagHelperActivator(new TypeActivatorCache());
+            var activator = new DefaultTagHelperActivator();
             var viewContext = CreateViewContext();
 
             var scriptTagHelper = activator.Create<ScriptTagHelper>(viewContext);
@@ -43,7 +42,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
         public void LinkTagHelper_DoesNotUseMemoryCacheInstanceFromDI()
         {
             // Arrange
-            var activator = new DefaultTagHelperActivator(new TypeActivatorCache());
+            var activator = new DefaultTagHelperActivator();
             var viewContext = CreateViewContext();
 
             var linkTagHelper = activator.Create<LinkTagHelper>(viewContext);