public void Endpoints_ReturnsAllEndpoints_FromMultipleDataSources() { // Arrange var endpoint1 = CreateEndpoint("/a"); var endpoint2 = CreateEndpoint("/b"); var endpoint3 = CreateEndpoint("/c"); var endpoint4 = CreateEndpoint("/d"); var endpoint5 = CreateEndpoint("/e"); var compositeDataSource = new CompositeEndpointDataSource(new[] { new DefaultEndpointDataSource(new Endpoint[] { endpoint1, endpoint2 }), new DefaultEndpointDataSource(new Endpoint[] { endpoint3, endpoint4 }), new DefaultEndpointDataSource(new Endpoint[] { endpoint5 }), }); // Act var endpoints = compositeDataSource.Endpoints; // Assert Assert.Collection( endpoints, (ep) => Assert.Same(endpoint1, ep), (ep) => Assert.Same(endpoint2, ep), (ep) => Assert.Same(endpoint3, ep), (ep) => Assert.Same(endpoint4, ep), (ep) => Assert.Same(endpoint5, ep)); }
public EndpointRoutingMiddleware( MatcherFactory matcherFactory, CompositeEndpointDataSource endpointDataSource, ILogger <EndpointRoutingMiddleware> logger, RequestDelegate next) { if (matcherFactory == null) { throw new ArgumentNullException(nameof(matcherFactory)); } if (endpointDataSource == null) { throw new ArgumentNullException(nameof(endpointDataSource)); } if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (next == null) { throw new ArgumentNullException(nameof(next)); } _matcherFactory = matcherFactory; _endpointDataSource = endpointDataSource; _logger = logger; _next = next; }
public NameBasedEndpointFinder( CompositeEndpointDataSource endpointDataSource, ILogger <NameBasedEndpointFinder> logger) { _endpointDatasource = endpointDataSource; _logger = logger; }
public DefaultLinkGenerator( ParameterPolicyFactory parameterPolicyFactory, CompositeEndpointDataSource dataSource, ObjectPool <UriBuildingContext> uriBuildingContextPool, IOptions <RouteOptions> routeOptions, ILogger <DefaultLinkGenerator> logger, IServiceProvider serviceProvider) { _parameterPolicyFactory = parameterPolicyFactory; _uriBuildingContextPool = uriBuildingContextPool; _logger = logger; _serviceProvider = serviceProvider; // We cache TemplateBinder instances per-Endpoint for performance, but we want to wipe out // that cache is the endpoints change so that we don't allow unbounded memory growth. _cache = new DataSourceDependentCache <ConcurrentDictionary <RouteEndpoint, TemplateBinder> >(dataSource, (_) => { // We don't eagerly fill this cache because there's no real reason to. Unlike URL matching, we don't // need to build a big data structure up front to be correct. return(new ConcurrentDictionary <RouteEndpoint, TemplateBinder>()); }); // Cached to avoid per-call allocation of a delegate on lookup. _createTemplateBinder = CreateTemplateBinder; _globalLinkOptions = new LinkOptions() { AppendTrailingSlash = routeOptions.Value.AppendTrailingSlash, LowercaseQueryStrings = routeOptions.Value.LowercaseQueryStrings, LowercaseUrls = routeOptions.Value.LowercaseUrls, }; }
public RouteValuesBasedEndpointFinder( CompositeEndpointDataSource endpointDataSource, ObjectPool <UriBuildingContext> objectPool, IInlineConstraintResolver inlineConstraintResolver) { _endpointDataSource = endpointDataSource; _objectPool = objectPool; _inlineConstraintResolver = inlineConstraintResolver; BuildOutboundMatches(); }
public RouteValuesBasedEndpointFinder( CompositeEndpointDataSource endpointDataSource, ObjectPool <UriBuildingContext> objectPool) { _endpointDataSource = endpointDataSource; _objectPool = objectPool; // Build initial matches BuildOutboundMatches(); // Register for changes in endpoints Extensions.Primitives.ChangeToken.OnChange( _endpointDataSource.GetChangeToken, HandleChange); }
public void CreatesShallowCopyOf_ListOfEndpoints() { // Arrange var endpoint1 = CreateEndpoint("/a"); var endpoint2 = CreateEndpoint("/b"); var dataSource = new DefaultEndpointDataSource(new Endpoint[] { endpoint1, endpoint2 }); var compositeDataSource = new CompositeEndpointDataSource(new[] { dataSource }); // Act var endpoints = compositeDataSource.Endpoints; // Assert Assert.NotSame(endpoints, dataSource.Endpoints); Assert.Equal(endpoints, dataSource.Endpoints); }
public void ConsumerChangeToken_IsRefreshed_WhenDataSourceCallbackFires() { // Arrange1 var endpoint1 = CreateEndpoint("/a"); var dataSource1 = new DynamicEndpointDataSource(endpoint1); var compositeDataSource = new CompositeEndpointDataSource(new[] { dataSource1 }); // Act1 var endpoints = compositeDataSource.Endpoints; // Assert1 var changeToken1 = compositeDataSource.GetChangeToken(); var token = Assert.IsType <CancellationChangeToken>(changeToken1); Assert.False(token.HasChanged); // initial state // Arrange2 var endpoint2 = CreateEndpoint("/b"); // Act2 dataSource1.AddEndpoint(endpoint2); // Assert2 Assert.True(changeToken1.HasChanged); // old token is expected to be changed var changeToken2 = compositeDataSource.GetChangeToken(); // new token is in a unchanged state Assert.NotSame(changeToken2, changeToken1); token = Assert.IsType <CancellationChangeToken>(changeToken2); Assert.False(token.HasChanged); // Arrange3 var endpoint3 = CreateEndpoint("/c"); // Act2 dataSource1.AddEndpoint(endpoint3); // Assert2 Assert.True(changeToken2.HasChanged); // old token is expected to be changed var changeToken3 = compositeDataSource.GetChangeToken(); // new token is in a unchanged state Assert.NotSame(changeToken3, changeToken2); Assert.NotSame(changeToken3, changeToken1); token = Assert.IsType <CancellationChangeToken>(changeToken3); Assert.False(token.HasChanged); }
public void DataSourceChanges_AreReflected_InEndpoints() { // Arrange1 var endpoint1 = CreateEndpoint("/a"); var dataSource1 = new DynamicEndpointDataSource(endpoint1); var compositeDataSource = new CompositeEndpointDataSource(new[] { dataSource1 }); // Act1 var endpoints = compositeDataSource.Endpoints; // Assert1 var endpoint = Assert.Single(endpoints); Assert.Same(endpoint1, endpoint); // Arrange2 var endpoint2 = CreateEndpoint("/b"); // Act2 dataSource1.AddEndpoint(endpoint2); // Assert2 Assert.Collection( compositeDataSource.Endpoints, (ep) => Assert.Same(endpoint1, ep), (ep) => Assert.Same(endpoint2, ep)); // Arrange3 var endpoint3 = CreateEndpoint("/c"); // Act2 dataSource1.AddEndpoint(endpoint3); // Assert2 Assert.Collection( compositeDataSource.Endpoints, (ep) => Assert.Same(endpoint1, ep), (ep) => Assert.Same(endpoint2, ep), (ep) => Assert.Same(endpoint3, ep)); }
// Initialization is async to avoid blocking threads while reflection and things // of that nature take place. // // We've seen cases where startup is very slow if we allow multiple threads to race // while initializing the set of endpoints/routes. Doing CPU intensive work is a // blocking operation if you have a low core count and enough work to do. private Task <Matcher> InitializeAsync() { if (_initializationTask != null) { return(_initializationTask); } var initializationTask = new TaskCompletionSource <Matcher>(); if (Interlocked.CompareExchange <Task <Matcher> >( ref _initializationTask, initializationTask.Task, null) == null) { // This thread won the race, do the initialization. var dataSource = new CompositeEndpointDataSource(_options.Value.DataSources); var matcher = _matcherFactory.CreateMatcher(dataSource); initializationTask.SetResult(matcher); } return(_initializationTask); }
public RouteValuesAddressScheme(CompositeEndpointDataSource dataSource) { _cache = new DataSourceDependentCache <StateEntry>(dataSource, Initialize); }
public IntAddressScheme(CompositeEndpointDataSource dataSource) { _dataSource = dataSource; }
public CustomRouteValuesBasedEndpointFinder( CompositeEndpointDataSource endpointDataSource, ObjectPool <UriBuildingContext> objectPool) : base(endpointDataSource, objectPool) { }
public CustomRouteValuesBasedAddressScheme(CompositeEndpointDataSource dataSource) : base(dataSource) { }
public EndpointNameAddressScheme(CompositeEndpointDataSource dataSource) { _cache = new DataSourceDependentCache <Dictionary <string, Endpoint[]> >(dataSource, Initialize); }