Skip to content

Commit 267217e

Browse files
committed
Added view component descriptor cache (#66)
1 parent 008e484 commit 267217e

8 files changed

Lines changed: 118 additions & 8 deletions

File tree

src/MyTested.AspNetCore.Mvc.Abstractions/Internal/Caching/ControllerActionDescriptorCache.cs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class ControllerActionDescriptorCache : IControllerActionDescriptorCache
1515
{
1616
private static readonly ConcurrentDictionary<MethodInfo, ControllerActionDescriptor> Cache =
1717
new ConcurrentDictionary<MethodInfo, ControllerActionDescriptor>();
18-
18+
1919
/// <summary>
2020
/// Initializes a new instance of the <see cref="ControllerActionDescriptorCache"/> class.
2121
/// </summary>
@@ -25,16 +25,12 @@ public ControllerActionDescriptorCache(IActionDescriptorCollectionProvider provi
2525
this.PrepareCache(provider);
2626
}
2727

28-
/// <summary>
29-
/// Gets the controller action descriptor for the provided method info.
30-
/// </summary>
31-
/// <param name="methodInfo">Method info of the controller action descriptor to get.</param>
32-
/// <returns>Controller action descriptor.</returns>
28+
/// <inheritdoc />
3329
public ControllerActionDescriptor GetActionDescriptor(MethodInfo methodInfo)
3430
{
3531
if (!Cache.Any())
3632
{
37-
throw new InvalidOperationException("Controller actions could not be found by the MVC application. Controllers may need to be added as services by calling 'AddMvc().AddControllersAsServices()' or 'AddMvcControllersAsServices()' on the service collection.");
33+
throw new InvalidOperationException("Controller actions could not be found by the MVC application. Controllers may need to be added as services by calling 'AddMvc().AddControllersAsServices()' on the service collection. You may also add the external controllers assembly as an application part by calling 'AddMvc().AddApplicationPart()'.");
3834
}
3935

4036
return this.TryGetActionDescriptor(methodInfo);

src/MyTested.AspNetCore.Mvc.Abstractions/Internal/Contracts/IControllerActionDescriptorCache.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
using Microsoft.AspNetCore.Mvc.Controllers;
55

66
/// <summary>
7-
/// Caches controller action descriptors by MethodInfo.
7+
/// Caches controller action descriptors by <see cref="MethodInfo"/>.
88
/// </summary>
99
public interface IControllerActionDescriptorCache
1010
{
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Contracts.Invocations
2+
{
3+
public interface IViewComponentResultTestBuilder<TInvocationResult>
4+
{
5+
}
6+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Invocations
2+
{
3+
using Base;
4+
using Contracts.Invocations;
5+
using Internal.TestContexts;
6+
7+
public class ViewComponentResultTestBuilder<TInvocationResult> : BaseTestBuilderWithViewComponent,
8+
IViewComponentResultTestBuilder<TInvocationResult>
9+
{
10+
public ViewComponentResultTestBuilder(ViewComponentTestContext testContext)
11+
: base(testContext)
12+
{
13+
}
14+
}
15+
}

src/MyTested.AspNetCore.Mvc.ViewComponents/Builders/ViewComponents/ViewComponentInvocationBuilder.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,28 @@
11
namespace MyTested.AspNetCore.Mvc.Builders.ViewComponents
22
{
3+
using System;
34
using System.Linq.Expressions;
45
using System.Reflection;
6+
using System.Threading.Tasks;
7+
using Contracts.Invocations;
8+
using Invocations;
59

610
public partial class ViewComponentBuilder<TViewComponent>
711
{
12+
/// <inheritdoc />
13+
public IViewComponentResultTestBuilder<TActionResult> InvokedWith<TActionResult>(Expression<Func<TViewComponent, TActionResult>> actionCall)
14+
{
15+
this.Invoke(actionCall);
16+
return new ViewComponentResultTestBuilder<TActionResult>(this.TestContext);
17+
}
18+
19+
/// <inheritdoc />
20+
public IViewComponentResultTestBuilder<TActionResult> InvokedWith<TActionResult>(Expression<Func<TViewComponent, Task<TActionResult>>> actionCall)
21+
{
22+
this.Invoke(actionCall);
23+
return new ViewComponentResultTestBuilder<TActionResult>(this.TestContext);
24+
}
25+
826
protected override void ProcessAndValidateMethod(LambdaExpression methodCall, MethodInfo methodInfo)
927
{
1028
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
namespace MyTested.AspNetCore.Mvc.Internal.Caching
2+
{
3+
using System;
4+
using System.Collections.Concurrent;
5+
using System.Linq;
6+
using System.Reflection;
7+
using Contracts;
8+
using Microsoft.AspNetCore.Mvc.ViewComponents;
9+
10+
/// <summary>
11+
/// Caches view component descriptors by <see cref="MethodInfo"/>.
12+
/// </summary>
13+
public class ViewComponentDescriptorCache : IViewComponentDescriptorCache
14+
{
15+
private static readonly ConcurrentDictionary<MethodInfo, ViewComponentDescriptor> Cache =
16+
new ConcurrentDictionary<MethodInfo, ViewComponentDescriptor>();
17+
18+
public ViewComponentDescriptorCache(IViewComponentDescriptorCollectionProvider provider)
19+
{
20+
this.PrepareCache(provider);
21+
}
22+
23+
/// <inheritdoc />
24+
public ViewComponentDescriptor GetViewComponentDescriptor(MethodInfo methodInfo)
25+
{
26+
if (!Cache.Any())
27+
{
28+
throw new InvalidOperationException("View components could not be found by the MVC application. View components may need to be added as services by calling 'AddMvc().AddViewComponentsAsServices()' on the service collection. You may also add the external view components assembly as an application part by calling 'AddMvc().AddApplicationPart()'.");
29+
}
30+
31+
return this.TryGetViewComponentDescriptor(methodInfo);
32+
}
33+
34+
/// <inheritdoc />
35+
public ViewComponentDescriptor TryGetViewComponentDescriptor(MethodInfo methodInfo)
36+
{
37+
ViewComponentDescriptor viewComponentDescriptor = null;
38+
Cache.TryGetValue(methodInfo, out viewComponentDescriptor);
39+
40+
return viewComponentDescriptor;
41+
}
42+
43+
private void PrepareCache(IViewComponentDescriptorCollectionProvider provider)
44+
{
45+
var viewComponentDescriptors = provider.ViewComponents.Items;
46+
47+
foreach (var descriptor in viewComponentDescriptors)
48+
{
49+
Cache.TryAdd(descriptor.MethodInfo, descriptor);
50+
}
51+
}
52+
}
53+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
namespace MyTested.AspNetCore.Mvc.Internal.Contracts
2+
{
3+
using Microsoft.AspNetCore.Mvc.ViewComponents;
4+
using System.Reflection;
5+
6+
/// <summary>
7+
/// Caches view component descriptors by <see cref="MethodInfo"/>.
8+
/// </summary>
9+
public interface IViewComponentDescriptorCache
10+
{
11+
/// <summary>
12+
/// Gets the view component descriptor for the provided method info.
13+
/// </summary>
14+
/// <param name="methodInfo">Method info of the view component descriptor to get.</param>
15+
/// <returns>View component descriptor.</returns>
16+
ViewComponentDescriptor GetViewComponentDescriptor(MethodInfo methodInfo);
17+
18+
ViewComponentDescriptor TryGetViewComponentDescriptor(MethodInfo methodInfo);
19+
}
20+
}

src/MyTested.AspNetCore.Mvc.ViewComponents/ServiceCollectionViewComponentsExtensions.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace MyTested.AspNetCore.Mvc
22
{
3+
using Internal.Caching;
34
using Internal.Contracts;
45
using Internal.ViewComponents;
56
using Microsoft.Extensions.DependencyInjection;
@@ -13,6 +14,7 @@ public static IServiceCollection AddViewComponentsTesting(this IServiceCollectio
1314
CommonValidator.CheckForNullReference(serviceCollection, nameof(serviceCollection));
1415

1516
serviceCollection.TryAddSingleton<IViewComponentPropertyActivator, ViewComponentPropertyActivator>();
17+
serviceCollection.TryAddSingleton<IViewComponentDescriptorCache, ViewComponentDescriptorCache>();
1618

1719
return serviceCollection;
1820
}

0 commit comments

Comments
 (0)