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

[Proposal] Generic accessor into feature collection #525

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/Microsoft.AspNet.Http.Features/FeatureCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace Microsoft.AspNet.Http.Features
{
Expand Down Expand Up @@ -93,6 +94,21 @@ public IEnumerator<KeyValuePair<Type, object>> GetEnumerator()
}
}

public TFeature Get<TFeature>()
{
var type = typeof(TFeature);
if (type.GetTypeInfo().IsValueType)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this check?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(TFeature)this[type] blows up if its a struct and not in the collection with a NRE

{
return default(TFeature);
}
return (TFeature)this[type];
}

public void Set<TFeature>(TFeature instance)
{
this[typeof(TFeature)] = instance;
}

private class KeyComparer : IEqualityComparer<KeyValuePair<Type, object>>
{
public bool Equals(KeyValuePair<Type, object> x, KeyValuePair<Type, object> y)
Expand Down
30 changes: 0 additions & 30 deletions src/Microsoft.AspNet.Http.Features/FeatureCollectionExtensions.cs

This file was deleted.

23 changes: 16 additions & 7 deletions src/Microsoft.AspNet.Http.Features/FeatureReferences.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,28 @@ public FeatureReferences(IFeatureCollection collection)

public TFeature Fetch<TFeature, TState>(
ref TFeature cached,
Func<TFeature> recheckCache,
TState state,
Func<TState, TFeature> factory)
{
var cleared = false;
if (Revision != Collection.Revision)
{
cleared = true;
Cache = default(TCache);
Cache = recheckCache != null ? Collection.Get<TCache>() : default(TCache);
Revision = Collection.Revision;
}

var feature = cached;
TFeature feature;
if (recheckCache != null && cleared)
{
feature = recheckCache();
}
else
{
feature = cached;
}

if (feature == null)
{
feature = Collection.Get<TFeature>();
Expand All @@ -45,18 +55,17 @@ public TFeature Fetch<TFeature, TState>(
feature = factory(state);

Collection.Set(feature);
if (!cleared)
{
Cache = default(TCache);
}
Revision = Collection.Revision;
}
cached = feature;
}
return feature;
}

public TFeature Fetch<TFeature>(ref TFeature cached, Func<TFeature> recheckCache, Func<IFeatureCollection, TFeature> factory) =>
Fetch(ref cached, recheckCache, Collection, factory);

public TFeature Fetch<TFeature>(ref TFeature cached, Func<IFeatureCollection, TFeature> factory) =>
Fetch(ref cached, Collection, factory);
Fetch(ref cached, null, Collection, factory);
}
}
14 changes: 14 additions & 0 deletions src/Microsoft.AspNet.Http.Features/IFeatureCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,19 @@ public interface IFeatureCollection : IEnumerable<KeyValuePair<Type, object>>
/// <param name="key"></param>
/// <returns>The requested feature, or null if it is not present.</returns>
object this[Type key] { get; set; }

/// <summary>
/// Retrieves the requested feature from the collection.
/// </summary>
/// <typeparam name="TFeature">The feature key.</typeparam>
/// <returns>The requested feature, or null if it is not present.</returns>
TFeature Get<TFeature>();

/// <summary>
/// Sets the given feature in the collection.
/// </summary>
/// <typeparam name="TFeature">The feature key.</typeparam>
/// <param name="instance">The feature value.</param>
void Set<TFeature>(TFeature instance);
}
}
16 changes: 5 additions & 11 deletions src/Microsoft.AspNet.Http/DefaultConnectionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Microsoft.AspNet.Http.Internal
{
public class DefaultConnectionInfo : ConnectionInfo
{
private FeatureReferences<FeatureInterfaces> _features;
private FeatureReferences<ConnectionFeatures> _features;

public DefaultConnectionInfo(IFeatureCollection features)
{
Expand All @@ -21,19 +21,19 @@ public DefaultConnectionInfo(IFeatureCollection features)

public virtual void Initialize( IFeatureCollection features)
{
_features = new FeatureReferences<FeatureInterfaces>(features);
_features = new FeatureReferences<ConnectionFeatures>(features);
}

public virtual void Uninitialize()
{
_features = default(FeatureReferences<FeatureInterfaces>);
_features = default(FeatureReferences<ConnectionFeatures>);
}

private IHttpConnectionFeature HttpConnectionFeature =>
_features.Fetch(ref _features.Cache.Connection, f => new HttpConnectionFeature());
_features.Fetch(ref _features.Cache.Connection, () => _features.Cache.Connection, f => new HttpConnectionFeature());

private ITlsConnectionFeature TlsConnectionFeature=>
_features.Fetch(ref _features.Cache.TlsConnection, f => new TlsConnectionFeature());
_features.Fetch(ref _features.Cache.TlsConnection, () => _features.Cache.TlsConnection, f => new TlsConnectionFeature());

public override IPAddress RemoteIpAddress
{
Expand Down Expand Up @@ -75,11 +75,5 @@ public override X509Certificate2 ClientCertificate
{
return TlsConnectionFeature.GetClientCertificateAsync(cancellationToken);
}

struct FeatureInterfaces
{
public IHttpConnectionFeature Connection;
public ITlsConnectionFeature TlsConnection;
}
}
}
31 changes: 10 additions & 21 deletions src/Microsoft.AspNet.Http/DefaultHttpContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace Microsoft.AspNet.Http.Internal
{
public class DefaultHttpContext : HttpContext
{
private FeatureReferences<FeatureInterfaces> _features;
private FeatureReferences<ContextFeatures> _features;

private HttpRequest _request;
private HttpResponse _response;
Expand All @@ -38,14 +38,14 @@ public DefaultHttpContext(IFeatureCollection features)

public virtual void Initialize(IFeatureCollection features)
{
_features = new FeatureReferences<FeatureInterfaces>(features);
_features = new FeatureReferences<ContextFeatures>(features);
_request = InitializeHttpRequest();
_response = InitializeHttpResponse();
}

public virtual void Uninitialize()
{
_features = default(FeatureReferences<FeatureInterfaces>);
_features = default(FeatureReferences<ContextFeatures>);
if (_request != null)
{
UninitializeHttpRequest(_request);
Expand Down Expand Up @@ -74,26 +74,25 @@ public virtual void Uninitialize()
}

private IItemsFeature ItemsFeature =>
_features.Fetch(ref _features.Cache.Items, f => new ItemsFeature());
_features.Fetch(ref _features.Cache.Items, () => _features.Cache.Items, f => new ItemsFeature());

private IServiceProvidersFeature ServiceProvidersFeature =>
_features.Fetch(ref _features.Cache.ServiceProviders, f => new ServiceProvidersFeature());
_features.Fetch(ref _features.Cache.ServiceProviders, () => _features.Cache.ServiceProviders, f => new ServiceProvidersFeature());

private IHttpAuthenticationFeature HttpAuthenticationFeature =>
_features.Fetch(ref _features.Cache.Authentication, f => new HttpAuthenticationFeature());
_features.Fetch(ref _features.Cache.Authentication, () => _features.Cache.Authentication, f => new HttpAuthenticationFeature());

private IHttpRequestLifetimeFeature LifetimeFeature =>
_features.Fetch(ref _features.Cache.Lifetime, f => new HttpRequestLifetimeFeature());
_features.Fetch(ref _features.Cache.Lifetime, () => _features.Cache.Lifetime, f => new HttpRequestLifetimeFeature());

private ISessionFeature SessionFeature =>
_features.Fetch(ref _features.Cache.Session, f => new DefaultSessionFeature());
_features.Fetch(ref _features.Cache.Session, () => _features.Cache.Session, f => new DefaultSessionFeature());

private ISessionFeature SessionFeatureOrNull =>
_features.Fetch(ref _features.Cache.Session, f => null);

_features.Fetch(ref _features.Cache.Session, () => _features.Cache.Session, f => null);

private IHttpRequestIdentifierFeature RequestIdentifierFeature =>
_features.Fetch(ref _features.Cache.RequestIdentifier, f => new HttpRequestIdentifierFeature());
_features.Fetch(ref _features.Cache.RequestIdentifier, () => _features.Cache.RequestIdentifier, f => new HttpRequestIdentifierFeature());

public override IFeatureCollection Features => _features.Collection;

Expand Down Expand Up @@ -187,15 +186,5 @@ protected virtual void UninitializeAuthenticationManager(AuthenticationManager i

protected virtual WebSocketManager InitializeWebSocketManager() => new DefaultWebSocketManager(Features);
protected virtual void UninitializeWebSocketManager(WebSocketManager instance) { }

struct FeatureInterfaces
{
public IItemsFeature Items;
public IServiceProvidersFeature ServiceProviders;
public IHttpAuthenticationFeature Authentication;
public IHttpRequestLifetimeFeature Lifetime;
public ISessionFeature Session;
public IHttpRequestIdentifierFeature RequestIdentifier;
}
}
}
22 changes: 7 additions & 15 deletions src/Microsoft.AspNet.Http/DefaultHttpRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Microsoft.AspNet.Http.Internal
public class DefaultHttpRequest : HttpRequest
{
private HttpContext _context;
private FeatureReferences<FeatureInterfaces> _features;
private FeatureReferences<RequestFeatures> _features;

public DefaultHttpRequest(HttpContext context, IFeatureCollection features)
{
Expand All @@ -24,28 +24,28 @@ public DefaultHttpRequest(HttpContext context, IFeatureCollection features)
public virtual void Initialize(HttpContext context, IFeatureCollection features)
{
_context = context;
_features = new FeatureReferences<FeatureInterfaces>(features);
_features = new FeatureReferences<RequestFeatures>(features);
}

public virtual void Uninitialize()
{
_context = null;
_features = default(FeatureReferences<FeatureInterfaces>);
_features = default(FeatureReferences<RequestFeatures>);
}

public override HttpContext HttpContext => _context;

private IHttpRequestFeature HttpRequestFeature =>
_features.Fetch(ref _features.Cache.Request, f => null);
_features.Fetch(ref _features.Cache.Request, () => _features.Cache.Request, f => null);

private IQueryFeature QueryFeature =>
_features.Fetch(ref _features.Cache.Query, f => new QueryFeature(f));
_features.Fetch(ref _features.Cache.Query, () => _features.Cache.Query, f => new QueryFeature(f));

private IFormFeature FormFeature =>
_features.Fetch(ref _features.Cache.Form, this, f => new FormFeature(f));
_features.Fetch(ref _features.Cache.Form, () => _features.Cache.Form, this, f => new FormFeature(f));

private IRequestCookiesFeature RequestCookiesFeature =>
_features.Fetch(ref _features.Cache.Cookies, f => new RequestCookiesFeature(f));
_features.Fetch(ref _features.Cache.Cookies, () => _features.Cache.Cookies, f => new RequestCookiesFeature(f));

public override PathString PathBase
{
Expand Down Expand Up @@ -151,13 +151,5 @@ public override Task<IFormCollection> ReadFormAsync(CancellationToken cancellati
{
return FormFeature.ReadFormAsync(cancellationToken);
}

struct FeatureInterfaces
{
public IHttpRequestFeature Request;
public IQueryFeature Query;
public IFormFeature Form;
public IRequestCookiesFeature Cookies;
}
}
}
16 changes: 5 additions & 11 deletions src/Microsoft.AspNet.Http/DefaultHttpResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Microsoft.AspNet.Http.Internal
public class DefaultHttpResponse : HttpResponse
{
private HttpContext _context;
private FeatureReferences<FeatureInterfaces> _features;
private FeatureReferences<ResponseFeatures> _features;

public DefaultHttpResponse(HttpContext context, IFeatureCollection features)
{
Expand All @@ -23,20 +23,20 @@ public DefaultHttpResponse(HttpContext context, IFeatureCollection features)
public virtual void Initialize(HttpContext context, IFeatureCollection features)
{
_context = context;
_features = new FeatureReferences<FeatureInterfaces>(features);
_features = new FeatureReferences<ResponseFeatures>(features);
}

public virtual void Uninitialize()
{
_context = null;
_features = default(FeatureReferences<FeatureInterfaces>);
_features = default(FeatureReferences<ResponseFeatures>);
}

private IHttpResponseFeature HttpResponseFeature =>
_features.Fetch(ref _features.Cache.Response, f => null);
_features.Fetch(ref _features.Cache.Response, () => _features.Cache.Response, f => null);

private IResponseCookiesFeature ResponseCookiesFeature =>
_features.Fetch(ref _features.Cache.Cookies, f => new ResponseCookiesFeature(f));
_features.Fetch(ref _features.Cache.Cookies, () => _features.Cache.Cookies, f => new ResponseCookiesFeature(f));


public override HttpContext HttpContext { get { return _context; } }
Expand Down Expand Up @@ -132,11 +132,5 @@ public override void Redirect(string location, bool permanent)

Headers[HeaderNames.Location] = location;
}

struct FeatureInterfaces
{
public IHttpResponseFeature Response;
public IResponseCookiesFeature Cookies;
}
}
}
Loading