Skip to content
This repository was archived by the owner on Dec 14, 2018. It is now read-only.

Commit 3e82cf1

Browse files
committed
[Fixes #4014] Implemented controllers feature based on feedback
1 parent 865acc7 commit 3e82cf1

File tree

18 files changed

+866
-837
lines changed

18 files changed

+866
-837
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Reflection;
5+
using System.Threading.Tasks;
6+
7+
namespace Microsoft.AspNetCore.Mvc.Controllers
8+
{
9+
public class ControllersFeature
10+
{
11+
public IList<TypeInfo> Controllers { get; } = new List<TypeInfo>();
12+
}
13+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Reflection;
5+
using System.Threading.Tasks;
6+
using Microsoft.AspNetCore.Mvc.ApplicationParts;
7+
8+
namespace Microsoft.AspNetCore.Mvc.Controllers
9+
{
10+
public class ControllersFeatureProvider : IApplicationFeatureProvider<ControllersFeature>
11+
{
12+
private const string ControllerTypeName = "Controller";
13+
14+
public void GetFeature(
15+
IEnumerable<ApplicationPart> parts,
16+
ControllersFeature feature)
17+
{
18+
foreach (var part in parts.OfType<IExportTypes>())
19+
{
20+
foreach (var type in part.Types)
21+
{
22+
if (IsController(type) && !feature.Controllers.Contains(type))
23+
{
24+
feature.Controllers.Add(type);
25+
}
26+
}
27+
}
28+
}
29+
30+
private bool IsController(TypeInfo typeInfo)
31+
{
32+
if (!typeInfo.IsClass)
33+
{
34+
return false;
35+
}
36+
37+
if (typeInfo.IsAbstract)
38+
{
39+
return false;
40+
}
41+
42+
// We only consider public top-level classes as controllers. IsPublic returns false for nested
43+
// classes, regardless of visibility modifiers
44+
if (!typeInfo.IsPublic)
45+
{
46+
return false;
47+
}
48+
49+
if (typeInfo.ContainsGenericParameters)
50+
{
51+
return false;
52+
}
53+
54+
if (typeInfo.IsDefined(typeof(NonControllerAttribute)))
55+
{
56+
return false;
57+
}
58+
59+
if (!typeInfo.Name.EndsWith(ControllerTypeName, StringComparison.OrdinalIgnoreCase) &&
60+
!typeInfo.IsDefined(typeof(ControllerAttribute)))
61+
{
62+
return false;
63+
}
64+
65+
return true;
66+
}
67+
}
68+
}

src/Microsoft.AspNetCore.Mvc.Core/Controllers/DefaultControllerTypeProvider.cs

Lines changed: 0 additions & 91 deletions
This file was deleted.

src/Microsoft.AspNetCore.Mvc.Core/Controllers/StaticControllerTypeProvider.cs

Lines changed: 0 additions & 46 deletions
This file was deleted.

src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreMvcBuilderExtensions.cs

Lines changed: 9 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
using Microsoft.AspNetCore.Mvc.Formatters;
99
using Microsoft.AspNetCore.Mvc.Internal;
1010
using System.Linq;
11+
using Microsoft.AspNetCore.Mvc.Controllers;
12+
using Microsoft.Extensions.DependencyInjection.Extensions;
1113

1214
namespace Microsoft.Extensions.DependencyInjection
1315
{
@@ -59,70 +61,22 @@ public static IMvcBuilder AddFormatterMappings(
5961
}
6062

6163
/// <summary>
62-
/// Register the specified <paramref name="controllerTypes"/> as services and as a source for controller
63-
/// discovery.
64+
/// Registers controllers as services in the <see cref="IServiceCollection"/>.
6465
/// </summary>
6566
/// <param name="builder">The <see cref="IMvcBuilder"/>.</param>
66-
/// <param name="controllerTypes">A sequence of controller <see cref="Type"/>s to register.</param>
6767
/// <returns>The <see cref="IMvcBuilder"/>.</returns>
68-
public static IMvcBuilder AddControllersAsServices(
69-
this IMvcBuilder builder,
70-
params Type[] controllerTypes)
68+
public static IMvcBuilder AddControllersAsServices(this IMvcBuilder builder)
7169
{
72-
return builder.AddControllersAsServices(controllerTypes.AsEnumerable());
73-
}
70+
var feature = new ControllersFeature();
71+
builder.Manager.PopulateFeature(feature);
7472

75-
/// <summary>
76-
/// Register the specified <paramref name="controllerTypes"/> as services and as a source for controller
77-
/// discovery.
78-
/// </summary>
79-
/// <param name="builder">The <see cref="IMvcBuilder"/>.</param>
80-
/// <param name="controllerTypes">A sequence of controller <see cref="Type"/>s to register.</param>
81-
/// <returns>The <see cref="IMvcBuilder"/>.</returns>
82-
public static IMvcBuilder AddControllersAsServices(
83-
this IMvcBuilder builder,
84-
IEnumerable<Type> controllerTypes)
85-
{
86-
if (builder == null)
73+
foreach (var controller in feature.Controllers.Select(c => c.AsType()))
8774
{
88-
throw new ArgumentNullException(nameof(builder));
75+
builder.Services.TryAddTransient(controller, controller);
8976
}
9077

91-
ControllersAsServices.AddControllersAsServices(builder.Services, controllerTypes);
92-
return builder;
93-
}
94-
95-
/// <summary>
96-
/// Registers controller types from the specified <paramref name="controllerAssemblies"/> as services and as a source
97-
/// for controller discovery.
98-
/// </summary>
99-
/// <param name="builder">The <see cref="IMvcBuilder"/>.</param>
100-
/// <param name="controllerAssemblies">Assemblies to scan.</param>
101-
/// <returns>The <see cref="IMvcBuilder"/>.</returns>
102-
public static IMvcBuilder AddControllersAsServices(
103-
this IMvcBuilder builder,
104-
params Assembly[] controllerAssemblies)
105-
{
106-
return builder.AddControllersAsServices(controllerAssemblies.AsEnumerable());
107-
}
108-
109-
/// <summary>
110-
/// Registers controller types from the specified <paramref name="controllerAssemblies"/> as services and as a source
111-
/// for controller discovery.
112-
/// </summary>
113-
/// <param name="builder">The <see cref="IMvcBuilder"/>.</param>
114-
/// <param name="controllerAssemblies">Assemblies to scan.</param>
115-
/// <returns>The <see cref="IMvcBuilder"/>.</returns>
116-
public static IMvcBuilder AddControllersAsServices(
117-
this IMvcBuilder builder,
118-
IEnumerable<Assembly> controllerAssemblies)
119-
{
120-
if (builder == null)
121-
{
122-
throw new ArgumentNullException(nameof(builder));
123-
}
78+
builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
12479

125-
ControllersAsServices.AddControllersAsServices(builder.Services, controllerAssemblies);
12680
return builder;
12781
}
12882
}

src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreMvcCoreBuilderExtensions.cs

Lines changed: 8 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Microsoft.AspNetCore.Mvc.Internal;
1212
using Microsoft.Extensions.DependencyInjection.Extensions;
1313
using System.Linq;
14+
using Microsoft.AspNetCore.Mvc.Controllers;
1415

1516
namespace Microsoft.Extensions.DependencyInjection
1617
{
@@ -96,70 +97,22 @@ internal static void AddAuthorizationServices(IServiceCollection services)
9697
}
9798

9899
/// <summary>
99-
/// Register the specified <paramref name="controllerTypes"/> as services and as a source for controller
100-
/// discovery.
100+
/// Registers discovered controllers as services in the <see cref="IServiceCollection"/>.
101101
/// </summary>
102102
/// <param name="builder">The <see cref="IMvcCoreBuilder"/>.</param>
103-
/// <param name="controllerTypes">A sequence of controller <see cref="Type"/>s to register.</param>
104103
/// <returns>The <see cref="IMvcCoreBuilder"/>.</returns>
105-
public static IMvcCoreBuilder AddControllersAsServices(
106-
this IMvcCoreBuilder builder,
107-
params Type[] controllerTypes)
104+
public static IMvcCoreBuilder AddControllersAsServices(this IMvcCoreBuilder builder)
108105
{
109-
return builder.AddControllersAsServices(controllerTypes.AsEnumerable());
110-
}
106+
var feature = new ControllersFeature();
107+
builder.Manager.PopulateFeature(feature);
111108

112-
/// <summary>
113-
/// Register the specified <paramref name="controllerTypes"/> as services and as a source for controller
114-
/// discovery.
115-
/// </summary>
116-
/// <param name="builder">The <see cref="IMvcCoreBuilder"/>.</param>
117-
/// <param name="controllerTypes">A sequence of controller <see cref="Type"/>s to register.</param>
118-
/// <returns>The <see cref="IMvcCoreBuilder"/>.</returns>
119-
public static IMvcCoreBuilder AddControllersAsServices(
120-
this IMvcCoreBuilder builder,
121-
IEnumerable<Type> controllerTypes)
122-
{
123-
if (builder == null)
109+
foreach (var controller in feature.Controllers.Select(c => c.AsType()))
124110
{
125-
throw new ArgumentNullException(nameof(builder));
111+
builder.Services.TryAddTransient(controller, controller);
126112
}
127113

128-
ControllersAsServices.AddControllersAsServices(builder.Services, controllerTypes);
129-
return builder;
130-
}
131-
132-
/// <summary>
133-
/// Registers controller types from the specified <paramref name="controllerAssemblies"/> as services and as a source
134-
/// for controller discovery.
135-
/// </summary>
136-
/// <param name="builder">The <see cref="IMvcCoreBuilder"/>.</param>
137-
/// <param name="controllerAssemblies">Assemblies to scan.</param>
138-
/// <returns>The <see cref="IMvcCoreBuilder"/>.</returns>
139-
public static IMvcCoreBuilder AddControllersAsServices(
140-
this IMvcCoreBuilder builder,
141-
params Assembly[] controllerAssemblies)
142-
{
143-
return builder.AddControllersAsServices(controllerAssemblies.AsEnumerable());
144-
}
145-
146-
/// <summary>
147-
/// Registers controller types from the specified <paramref name="controllerAssemblies"/> as services and as a source
148-
/// for controller discovery.
149-
/// </summary>
150-
/// <param name="builder">The <see cref="IMvcCoreBuilder"/>.</param>
151-
/// <param name="controllerAssemblies">Assemblies to scan.</param>
152-
/// <returns>The <see cref="IMvcCoreBuilder"/>.</returns>
153-
public static IMvcCoreBuilder AddControllersAsServices(
154-
this IMvcCoreBuilder builder,
155-
IEnumerable<Assembly> controllerAssemblies)
156-
{
157-
if (builder == null)
158-
{
159-
throw new ArgumentNullException(nameof(builder));
160-
}
114+
builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
161115

162-
ControllersAsServices.AddControllersAsServices(builder.Services, controllerAssemblies);
163116
return builder;
164117
}
165118
}

0 commit comments

Comments
 (0)