diff --git a/src/Microsoft.AspNetCore.Dispatcher.Abstractions/EndpointHandlerFactory.cs b/src/Microsoft.AspNetCore.Dispatcher.Abstractions/EndpointHandlerFactory.cs
deleted file mode 100644
index 54f5c2676b..0000000000
--- a/src/Microsoft.AspNetCore.Dispatcher.Abstractions/EndpointHandlerFactory.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-// 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;
-using Microsoft.AspNetCore.Http;
-
-namespace Microsoft.AspNetCore.Dispatcher
-{
- ///
- /// A delegate which attempts to create a for the selected .
- ///
- /// The selected by the dispatcher.
- ///
- /// A that invokes the operation represented by the , or null.
- ///
- public delegate Func EndpointHandlerFactory(Endpoint endpoint);
-}
diff --git a/src/Microsoft.AspNetCore.Dispatcher/CompositeHandlerFactory.cs b/src/Microsoft.AspNetCore.Dispatcher/CompositeHandlerFactory.cs
new file mode 100644
index 0000000000..ab7ae23b81
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Dispatcher/CompositeHandlerFactory.cs
@@ -0,0 +1,44 @@
+// 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;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.AspNetCore.Http;
+
+namespace Microsoft.AspNetCore.Dispatcher
+{
+ public class CompositeHandlerFactory : IHandlerFactory
+ {
+ private readonly IHandlerFactory[] _factories;
+
+ public CompositeHandlerFactory(IEnumerable factories)
+ {
+ if (factories == null)
+ {
+ throw new ArgumentNullException(nameof(factories));
+ }
+
+ _factories = factories.ToArray();
+ }
+
+ public Func CreateHandler(Endpoint endpoint)
+ {
+ if (endpoint == null)
+ {
+ throw new ArgumentNullException(nameof(endpoint));
+ }
+
+ for (var i = 0; i < _factories.Length; i++)
+ {
+ var handler = _factories[i].CreateHandler(endpoint);
+ if (handler != null)
+ {
+ return handler;
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/Microsoft.AspNetCore.Dispatcher/DefaultDispatcherConfigureOptions.cs b/src/Microsoft.AspNetCore.Dispatcher/DefaultDispatcherConfigureOptions.cs
index f372a2812f..7b54aaf76d 100644
--- a/src/Microsoft.AspNetCore.Dispatcher/DefaultDispatcherConfigureOptions.cs
+++ b/src/Microsoft.AspNetCore.Dispatcher/DefaultDispatcherConfigureOptions.cs
@@ -12,13 +12,13 @@ namespace Microsoft.AspNetCore.Dispatcher
private readonly IEnumerable _dataSources;
private readonly IDefaultMatcherFactory _dispatcherFactory;
private readonly IEnumerable _endpointSelectors;
- private readonly IEnumerable _handlerFactories;
+ private readonly IEnumerable _handlerFactories;
public DefaultDispatcherConfigureOptions(
IDefaultMatcherFactory dispatcherFactory,
IEnumerable dataSources,
IEnumerable endpointSelectors,
- IEnumerable handlerFactories)
+ IEnumerable handlerFactories)
{
_dispatcherFactory = dispatcherFactory;
_dataSources = dataSources;
@@ -33,12 +33,15 @@ namespace Microsoft.AspNetCore.Dispatcher
throw new ArgumentNullException(nameof(options));
}
- options.Matchers.Add(_dispatcherFactory.CreateDispatcher(new CompositeDispatcherDataSource(_dataSources), _endpointSelectors));
-
- foreach (var handlerFactory in _handlerFactories)
+ var matcher = _dispatcherFactory.CreateMatcher(new CompositeDispatcherDataSource(_dataSources), _endpointSelectors);
+
+ options.Matchers.Add(new MatcherEntry()
{
- options.HandlerFactories.Add(handlerFactory.CreateHandler);
- }
+ Matcher = matcher,
+ AddressProvider = matcher as IAddressCollectionProvider,
+ EndpointProvider = matcher as IEndpointCollectionProvider,
+ HandlerFactory = new CompositeHandlerFactory(_handlerFactories),
+ });
}
}
}
diff --git a/src/Microsoft.AspNetCore.Dispatcher/DispatcherMiddleware.cs b/src/Microsoft.AspNetCore.Dispatcher/DispatcherMiddleware.cs
index 211061e088..c13ad2fefd 100644
--- a/src/Microsoft.AspNetCore.Dispatcher/DispatcherMiddleware.cs
+++ b/src/Microsoft.AspNetCore.Dispatcher/DispatcherMiddleware.cs
@@ -63,15 +63,10 @@ namespace Microsoft.AspNetCore.Dispatcher
feature.Endpoint = context.Endpoint;
feature.Values = context.Values;
- // Associate this with the DispatcherEntry, not global
- for (var i = 0; i < _options.HandlerFactories.Count; i++)
+ feature.Handler = entry.HandlerFactory.CreateHandler(feature.Endpoint);
+ if (feature.Handler == null)
{
- var middleware = _options.HandlerFactories[i](feature.Endpoint);
- if (middleware != null)
- {
- feature.Handler = middleware;
- break;
- }
+ throw new InvalidOperationException("Couldn't create a handler, that's bad.");
}
break;
diff --git a/src/Microsoft.AspNetCore.Dispatcher/DispatcherOptions.cs b/src/Microsoft.AspNetCore.Dispatcher/DispatcherOptions.cs
index cffea2f891..1df9f50cc9 100644
--- a/src/Microsoft.AspNetCore.Dispatcher/DispatcherOptions.cs
+++ b/src/Microsoft.AspNetCore.Dispatcher/DispatcherOptions.cs
@@ -8,7 +8,5 @@ namespace Microsoft.AspNetCore.Dispatcher
public class DispatcherOptions
{
public MatcherCollection Matchers { get; } = new MatcherCollection();
-
- public IList HandlerFactories { get; } = new List();
}
}
diff --git a/src/Microsoft.AspNetCore.Dispatcher/DispatcherServiceCollectionExtensions.cs b/src/Microsoft.AspNetCore.Dispatcher/DispatcherServiceCollectionExtensions.cs
index 31e9ef190c..914b6f6106 100644
--- a/src/Microsoft.AspNetCore.Dispatcher/DispatcherServiceCollectionExtensions.cs
+++ b/src/Microsoft.AspNetCore.Dispatcher/DispatcherServiceCollectionExtensions.cs
@@ -27,7 +27,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddSingleton();
services.AddSingleton();
- services.TryAddEnumerable(ServiceDescriptor.Singleton());
+ services.TryAddEnumerable(ServiceDescriptor.Singleton());
return services;
}
diff --git a/src/Microsoft.AspNetCore.Dispatcher/HandlerFactory.cs b/src/Microsoft.AspNetCore.Dispatcher/HandlerFactory.cs
new file mode 100644
index 0000000000..98d6d83ce4
--- /dev/null
+++ b/src/Microsoft.AspNetCore.Dispatcher/HandlerFactory.cs
@@ -0,0 +1,42 @@
+// 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;
+using Microsoft.AspNetCore.Http;
+
+namespace Microsoft.AspNetCore.Dispatcher
+{
+ ///
+ /// A simple implementation of that adapts a particular endpoint
+ /// type to a handler.
+ ///
+ public sealed class HandlerFactory : IHandlerFactory
+ {
+ private readonly Func> _adapter;
+
+ public HandlerFactory(Func> adapter)
+ {
+ if (adapter == null)
+ {
+ throw new ArgumentNullException(nameof(adapter));
+ }
+
+ _adapter = adapter;
+ }
+
+ public Func CreateHandler(Endpoint endpoint)
+ {
+ if (endpoint == null)
+ {
+ throw new ArgumentNullException(nameof(endpoint));
+ }
+
+ if (endpoint is TEndpoint myTypeOfEndpoint)
+ {
+ return _adapter(myTypeOfEndpoint);
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/Microsoft.AspNetCore.Dispatcher/IDefaultMatcherFactory.cs b/src/Microsoft.AspNetCore.Dispatcher/IDefaultMatcherFactory.cs
index a98b281af8..45a7ace09d 100644
--- a/src/Microsoft.AspNetCore.Dispatcher/IDefaultMatcherFactory.cs
+++ b/src/Microsoft.AspNetCore.Dispatcher/IDefaultMatcherFactory.cs
@@ -7,6 +7,6 @@ namespace Microsoft.AspNetCore.Dispatcher
{
public interface IDefaultMatcherFactory
{
- MatcherEntry CreateDispatcher(DispatcherDataSource dataSource, IEnumerable endpointSelectors);
+ IMatcher CreateMatcher(DispatcherDataSource dataSource, IEnumerable endpointSelectors);
}
}
diff --git a/src/Microsoft.AspNetCore.Dispatcher/EndpointHandlerFactoryBase.cs b/src/Microsoft.AspNetCore.Dispatcher/IHandlerFactory.cs
similarity index 65%
rename from src/Microsoft.AspNetCore.Dispatcher/EndpointHandlerFactoryBase.cs
rename to src/Microsoft.AspNetCore.Dispatcher/IHandlerFactory.cs
index 6aeadb855c..f534cfb642 100644
--- a/src/Microsoft.AspNetCore.Dispatcher/EndpointHandlerFactoryBase.cs
+++ b/src/Microsoft.AspNetCore.Dispatcher/IHandlerFactory.cs
@@ -8,20 +8,20 @@ namespace Microsoft.AspNetCore.Dispatcher
{
///
///
- /// Base class for implementations that can create a middleware-like delegate from an .
+ /// An interface for components that can create a middleware-like delegate from an .
///
///
- /// Implementations registered in the application services using the service type
- /// will be automatically added to .
+ /// Implementations registered in the application services using the service type
+ /// will be automatically added to set of handler factories used by the default dispatcher.
///
///
- public abstract class EndpointHandlerFactoryBase
+ public interface IHandlerFactory
{
///
/// Creates a middleware-like delegate for the provided .
///
/// The that will execute for the current request.
/// An or null.
- public abstract Func CreateHandler(Endpoint endpoint);
+ Func CreateHandler(Endpoint endpoint);
}
}
diff --git a/src/Microsoft.AspNetCore.Dispatcher/MatcherCollection.cs b/src/Microsoft.AspNetCore.Dispatcher/MatcherCollection.cs
index 586caafeb9..b2dbe8a6bf 100644
--- a/src/Microsoft.AspNetCore.Dispatcher/MatcherCollection.cs
+++ b/src/Microsoft.AspNetCore.Dispatcher/MatcherCollection.cs
@@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Dispatcher
{
public class MatcherCollection : Collection
{
- public void Add(MatcherBase matcher)
+ public void Add(IMatcher matcher, IHandlerFactory handerFactory)
{
if (matcher == null)
{
@@ -18,21 +18,10 @@ namespace Microsoft.AspNetCore.Dispatcher
Add(new MatcherEntry()
{
Matcher = matcher,
- AddressProvider = matcher,
- EndpointProvider = matcher,
- });
- }
+ AddressProvider = matcher as IAddressCollectionProvider,
+ EndpointProvider = matcher as IEndpointCollectionProvider,
- public void Add(IMatcher matcher)
- {
- if (matcher == null)
- {
- throw new ArgumentNullException(nameof(matcher));
- }
-
- Add(new MatcherEntry()
- {
- Matcher = matcher,
+ HandlerFactory = handerFactory,
});
}
}
diff --git a/src/Microsoft.AspNetCore.Dispatcher/MatcherEntry.cs b/src/Microsoft.AspNetCore.Dispatcher/MatcherEntry.cs
index 0f32c5eaea..2bc36a44b9 100644
--- a/src/Microsoft.AspNetCore.Dispatcher/MatcherEntry.cs
+++ b/src/Microsoft.AspNetCore.Dispatcher/MatcherEntry.cs
@@ -5,6 +5,8 @@ namespace Microsoft.AspNetCore.Dispatcher
{
public class MatcherEntry
{
+ public IHandlerFactory HandlerFactory { get; set; }
+
public IMatcher Matcher { get; set; }
public IAddressCollectionProvider AddressProvider { get; set; }
diff --git a/src/Microsoft.AspNetCore.Dispatcher/TemplateEndpointHandlerFactory.cs b/src/Microsoft.AspNetCore.Dispatcher/TemplateEndpointHandlerFactory.cs
index a3544d1e89..f90c146a4c 100644
--- a/src/Microsoft.AspNetCore.Dispatcher/TemplateEndpointHandlerFactory.cs
+++ b/src/Microsoft.AspNetCore.Dispatcher/TemplateEndpointHandlerFactory.cs
@@ -6,9 +6,9 @@ using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Dispatcher
{
- public class TemplateEndpointHandlerFactory : EndpointHandlerFactoryBase
+ public sealed class TemplateEndpointHandlerFactory : IHandlerFactory
{
- public override Func CreateHandler(Endpoint endpoint)
+ public Func CreateHandler(Endpoint endpoint)
{
if (endpoint == null)
{
diff --git a/src/Microsoft.AspNetCore.Routing/Dispatcher/TreeMatcherFactory.cs b/src/Microsoft.AspNetCore.Routing/Dispatcher/TreeMatcherFactory.cs
index 213a0791a4..694ebe6b67 100644
--- a/src/Microsoft.AspNetCore.Routing/Dispatcher/TreeMatcherFactory.cs
+++ b/src/Microsoft.AspNetCore.Routing/Dispatcher/TreeMatcherFactory.cs
@@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Routing.Dispatcher
{
public class TreeMatcherFactory : IDefaultMatcherFactory
{
- public MatcherEntry CreateDispatcher(DispatcherDataSource dataSource, IEnumerable endpointSelectors)
+ public IMatcher CreateMatcher(DispatcherDataSource dataSource, IEnumerable endpointSelectors)
{
if (dataSource == null)
{
@@ -26,12 +26,7 @@ namespace Microsoft.AspNetCore.Routing.Dispatcher
matcher.Selectors.Add(endpointSelector);
}
- return new MatcherEntry()
- {
- AddressProvider = matcher,
- Matcher = matcher,
- EndpointProvider = matcher,
- };
+ return matcher;
}
}
}
diff --git a/test/Microsoft.AspNetCore.Dispatcher.FunctionalTest/ApiAppStartup.cs b/test/Microsoft.AspNetCore.Dispatcher.FunctionalTest/ApiAppStartup.cs
index bc3e8017d1..1b3d707636 100644
--- a/test/Microsoft.AspNetCore.Dispatcher.FunctionalTest/ApiAppStartup.cs
+++ b/test/Microsoft.AspNetCore.Dispatcher.FunctionalTest/ApiAppStartup.cs
@@ -72,9 +72,8 @@ namespace Microsoft.AspNetCore.Dispatcher.FunctionalTest
Selectors =
{
new HttpMethodEndpointSelector(),
- }
- });
- options.HandlerFactories.Add(endpoint => (endpoint as TemplateEndpoint)?.HandlerFactory);
+ },
+ }, new TemplateEndpointHandlerFactory());
}
private Task Products_Fallback(HttpContext httpContext) => httpContext.Response.WriteAsync("Hello, Products_Fallback");