Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make restier work with WAO 6.x and ODL 7.x #497

Merged
merged 2 commits into from
Aug 26, 2016
Merged
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
1 change: 1 addition & 0 deletions src/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Diagnostics.CodeAnalysis;

#region Permanent Exclusions
[assembly: SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Scope = "member", Target = "Microsoft.Restier.Providers.EntityFramework.EntityFrameworkApi`1.#ConfigureApi(System.Type,Microsoft.Extensions.DependencyInjection.IServiceCollection)")]
[assembly: SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Scope = "member", Target = "Microsoft.Restier.Core.Query.QueryRequest.#Create`2(System.Linq.IQueryable`1<!!0>,System.Linq.Expressions.Expression`1<System.Func`2<System.Linq.IQueryable`1<!!0>,!!1>>,System.Nullable`1<System.Boolean>)")]
[assembly: SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors", Scope = "type", Target = "Microsoft.Restier.Core.Submit.ChangeSetValidationException", Justification = "We do not intend to support serialization of this exception yet")]
[assembly: SuppressMessage("Microsoft.Design", "CA1061:DoNotHideBaseClassMethods", Scope = "member", Target = "Microsoft.Restier.Publishers.OData.Batch.RestierBatchChangeSetRequestItem.#DisposeResponses(System.Collections.Generic.IEnumerable`1<System.Net.Http.HttpResponseMessage>)")]
Expand Down
123 changes: 46 additions & 77 deletions src/Microsoft.Restier.Core/ApiBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,31 @@ namespace Microsoft.Restier.Core
/// </remarks>
public abstract class ApiBase : IDisposable
{
private static readonly ConcurrentDictionary<Type, ApiConfiguration> Configurations =
new ConcurrentDictionary<Type, ApiConfiguration>();

private ApiConfiguration apiConfiguration;
private ApiContext apiContext;
private IServiceProvider serviceProvider;

/// <summary>
/// Initializes a new instance of the <see cref="ApiBase" /> class.
/// </summary>
/// <param name="serviceProvider">
/// An <see cref="IServiceProvider"/> containing all services of this <see cref="ApiConfiguration"/>.
/// </param>
protected ApiBase(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}

/// <summary>
/// Gets the <see cref="IServiceProvider"/> which contains all services of this <see cref="ApiConfiguration"/>.
/// </summary>
public IServiceProvider ServiceProvider
{
get
{
return serviceProvider;
}
}

/// <summary>
/// Gets the API context for this API.
Expand All @@ -41,13 +61,7 @@ public ApiContext Context

if (this.apiContext == null)
{
this.apiContext = this.CreateApiContext(
this.Configuration);
var apiScope = this.apiContext.GetApiService<ApiHolder>();
if (apiScope != null)
{
apiScope.Api = this;
}
this.apiContext = serviceProvider.GetService<ApiContext>();
}

return this.apiContext;
Expand All @@ -60,66 +74,34 @@ public ApiContext Context
public bool IsDisposed { get; private set; }

/// <summary>
/// Gets or sets the API configuration for this API.
/// Gets the API configuration for this API.
/// </summary>
public ApiConfiguration Configuration
{
get
{
if (this.apiConfiguration != null)
if (this.apiConfiguration == null)
{
return this.apiConfiguration;
this.apiConfiguration = serviceProvider.GetService<ApiConfiguration>();
}

Configurations.TryGetValue(this.GetType(), out this.apiConfiguration);
return this.apiConfiguration;
}

set
{
this.apiConfiguration = value;
bool isSuccess = Configurations.TryAdd(GetType(), apiConfiguration);
if (isSuccess)
{
UpdateApiConfiguration(this.apiConfiguration);
}
}
}

/// <summary>
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
if (this.IsDisposed)
{
return;
}

this.IsDisposed = true;

if (this.apiContext != null)
{
this.apiContext.DisposeScope();
this.apiContext = null;
}

GC.SuppressFinalize(this);
}

/// <summary>
/// Configure services for this API.
/// </summary>
/// <param name="apiType">
/// The Api type.
/// </param>
/// <param name="services">
/// The <see cref="IServiceCollection"/> with which to create an <see cref="ApiConfiguration"/>.
/// The <see cref="IServiceCollection"/> with which is used to store all services.
/// </param>
/// <returns>The <see cref="IServiceCollection"/>.</returns>
[CLSCompliant(false)]
public virtual IServiceCollection ConfigureApi(IServiceCollection services)
public static IServiceCollection ConfigureApi(Type apiType, IServiceCollection services)
{
Type apiType = this.GetType();

// Add core and convention's services
services = services.AddCoreServices(apiType)
.AddConventionBasedServices(apiType);
Expand All @@ -131,37 +113,24 @@ public virtual IServiceCollection ConfigureApi(IServiceCollection services)
}

/// <summary>
/// Allow user to update the ApiConfiguration
/// <see cref="ApiConfiguration"/>.
/// Performs application-defined tasks associated with
/// freeing, releasing, or resetting unmanaged resources.
/// </summary>
/// <param name="configuration">The <see cref="ApiConfiguration"/> for the Api instance.</param>
[CLSCompliant(false)]
protected virtual void UpdateApiConfiguration(ApiConfiguration configuration)
public void Dispose()
{
}
if (this.IsDisposed)
{
return;
}

/// <summary>
/// Creates the API context for this API.
/// Descendants may further configure the built <see cref="ApiContext"/>.
/// </summary>
/// <param name="configuration">
/// The API configuration to use.
/// </param>
/// <returns>
/// The API context for this API.
/// </returns>
protected virtual ApiContext CreateApiContext(
ApiConfiguration configuration)
{
return new ApiContext(configuration);
}
this.IsDisposed = true;

// Registered as a scoped service so that IApi and ApiContext could be exposed as scoped service.
// If a descendant class wants to expose these 2 services in another way, it must ensure they could be
// resolved after CreateApiContext call.
internal class ApiHolder
{
public ApiBase Api { get; set; }
if (this.apiContext != null)
{
this.apiContext = null;
}

GC.SuppressFinalize(this);
}
}
}
34 changes: 7 additions & 27 deletions src/Microsoft.Restier.Core/ApiConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,45 +30,25 @@ public class ApiConfiguration

private static Action<IServiceCollection> emptyConfig = _ => { };

private IServiceProvider serviceProvider;

private Task<IEdmModel> modelTask;

/// <summary>
/// Initializes a new instance of the <see cref="ApiConfiguration" /> class.
/// </summary>
/// <param name="serviceProvider">
/// An <see cref="IServiceProvider"/> containing all services of this <see cref="ApiConfiguration"/>.
/// </param>
public ApiConfiguration(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}

/// <summary>
/// Gets the <see cref="IServiceProvider"/> which contains all services of this <see cref="ApiConfiguration"/>.
/// </summary>
internal IServiceProvider ServiceProvider
{
get { return serviceProvider; }
}

internal IEdmModel Model { get; private set; }

/// <summary>
/// Adds a configuration procedure for API type <typeparamref name="TApi"/>.
/// Adds a configuration procedure for apiType.
/// This is expected to be called by publisher like WebApi to add services.
/// </summary>
/// <typeparam name="TApi">The API type.</typeparam>
/// <param name="apiType">
/// The Api Type.
/// </param>
/// <param name="configurationCallback">
/// An action that will be called during the configuration of <typeparamref name="TApi"/>.
/// An action that will be called during the configuration of apiType.
/// </param>
[CLSCompliant(false)]
public static void AddPublisherServices<TApi>(Action<IServiceCollection> configurationCallback)
where TApi : ApiBase
public static void AddPublisherServices(Type apiType, Action<IServiceCollection> configurationCallback)
{
publisherServicesCallback.AddOrUpdate(
typeof(TApi),
apiType,
configurationCallback,
(type, existing) => existing + configurationCallback);
}
Expand Down
133 changes: 0 additions & 133 deletions src/Microsoft.Restier.Core/ApiConfigurationExtensions.cs

This file was deleted.

Loading