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 some APi public to facilitate some advance use case #506

Merged
merged 2 commits into from
Sep 1, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,14 @@ The release of the component binaries is carried out regularly through [Nuget](h
## 4. Documentation
Please visit the [RESTier pages](http://odata.github.io/RESTier). It has detailed descriptions on each feature provided by RESTier.

## 5. Community
### 5.1 Contribution
## 5. Sample services
Refer to [sample service github](https://github.com/OData/ODataSamples/tree/master/RESTier) for end to end sample service. The source code also contains end to end service for end to end test purpose. All the sample service can be run with visual studio 2015.

## 6. Community
### 6.1 Contribution
There are many ways for you to contribute to RESTier. The easiest way is to participate in discussion of features and issues. You can also contribute by sending pull requests of features or bug fixes to us. Contribution to the documentations is also highly welcomed. Please refer to the [CONTRIBUTING.md](https://github.com/OData/RESTier/blob/master/.github/CONTRIBUTING.md) for more details.

### 5.2 Support
### 6.2 Support
- Issues<br />Report issues on [Github issues](https://github.com/OData/RESTier/issues).
- Questions<br />Ask questions on [Stack Overflow](http://stackoverflow.com/questions/ask?tags=odata).
- Feedback<br />Please send mails to [odatafeedback@microsoft.com](mailto:odatafeedback@microsoft.com).
Expand Down
5 changes: 3 additions & 2 deletions src/Microsoft.Restier.Core/ApiBaseExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -524,13 +524,14 @@ public static void ClearProperty(this ApiBase api, string name)
var mapper = api.GetApiService<IModelMapper>();
if (mapper != null)
{
var modelContext = new ModelContext(api.ServiceProvider);
if (namespaceName == null)
{
mapper.TryGetRelevantType(api, name, out elementType);
mapper.TryGetRelevantType(modelContext, name, out elementType);
}
else
{
mapper.TryGetRelevantType(api, namespaceName, name, out elementType);
mapper.TryGetRelevantType(modelContext, namespaceName, name, out elementType);
}
}

Expand Down
12 changes: 6 additions & 6 deletions src/Microsoft.Restier.Core/Model/IModelMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ public interface IModelMapper
/// Tries to get the relevant type of an entity
/// set, singleton, or composable function import.
/// </summary>
/// <param name="apiBase">
/// An API.
/// <param name="context">
/// The context for model mapper.
/// </param>
/// <param name="name">
/// The name of an entity set, singleton or composable function import.
Expand Down Expand Up @@ -48,15 +48,15 @@ public interface IModelMapper
/// </para>
/// </remarks>
bool TryGetRelevantType(
ApiBase apiBase,
ModelContext context,
string name,
out Type relevantType);

/// <summary>
/// Tries to get the relevant type of a composable function.
/// </summary>
/// <param name="apiBase">
/// An API.
/// <param name="context">
/// The context for model mapper.
/// </param>
/// <param name="namespaceName">
/// The name of a namespace containing a composable function.
Expand Down Expand Up @@ -85,7 +85,7 @@ public interface IModelMapper
/// </para>
/// </remarks>
bool TryGetRelevantType(
ApiBase apiBase,
ModelContext context,
string namespaceName,
string name,
out Type relevantType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ public ModelMapper(Type dbContextType)
/// Tries to get the relevant type of an entity
/// set, singleton, or composable function import.
/// </summary>
/// <param name="apiBase">
/// An API.
/// <param name="context">
/// The context for model mapper.
/// </param>
/// <param name="name">
/// The name of an entity set, singleton or composable function import.
Expand All @@ -50,7 +50,7 @@ public ModelMapper(Type dbContextType)
/// provided; otherwise, <c>false</c>.
/// </returns>
public bool TryGetRelevantType(
ApiBase apiBase,
ModelContext context,
string name,
out Type relevantType)
{
Expand All @@ -77,8 +77,8 @@ public ModelMapper(Type dbContextType)
/// <summary>
/// Tries to get the relevant type of a composable function.
/// </summary>
/// <param name="apiBase">
/// An API.
/// <param name="context">
/// The context for model mapper.
/// </param>
/// <param name="namespaceName">
/// The name of a namespace containing a composable function.
Expand All @@ -95,7 +95,7 @@ public ModelMapper(Type dbContextType)
/// provided; otherwise, <c>false</c>.
/// </returns>
public bool TryGetRelevantType(
ApiBase apiBase,
ModelContext context,
string namespaceName,
string name,
out Type relevantType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public Task<IEdmModel> GetModelAsync(ModelContext context, CancellationToken can
Ensure.NotNull(context, "context");

#if EF7
var dbContext = context.ServiceProvider.GetService<DbContext>();
var dbContext = context.GetApiService<DbContext>();
context.ResourceSetTypeMap = dbContext.GetType().GetProperties()
.Where(e => e.PropertyType.FindGenericType(typeof(DbSet<>)) != null)
.ToDictionary(e => e.Name, e => e.PropertyType.GetGenericArguments()[0]);
Expand All @@ -59,7 +59,7 @@ public Task<IEdmModel> GetModelAsync(ModelContext context, CancellationToken can
#else
var resourceSetTypeMap = new Dictionary<string, Type>();
var resourceTypeKeyPropertiesMap = new Dictionary<Type, ICollection<PropertyInfo>>();
var dbContext = context.ServiceProvider.GetService<DbContext>();
var dbContext = context.GetApiService<DbContext>();

var efModel = (dbContext as IObjectContextAdapter).ObjectContext.MetadataWorkspace;
var efEntityContainer = efModel.GetItems<EntityContainer>(DataSpace.CSpace).Single();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class ChangeSetInitializer : IChangeSetInitializer
SubmitContext context,
CancellationToken cancellationToken)
{
DbContext dbContext = context.ServiceProvider.GetService<DbContext>();
DbContext dbContext = context.GetApiService<DbContext>();

foreach (var entry in context.ChangeSet.Entries.OfType<DataModificationItem>())
{
Expand Down Expand Up @@ -145,7 +145,7 @@ public virtual object ConvertToEfValue(Type type, object value)
DataModificationItem item,
CancellationToken cancellationToken)
{
var apiBase = context.ServiceProvider.GetService<ApiBase>();
var apiBase = context.GetApiService<ApiBase>();
IQueryable query = apiBase.GetQueryableSource(item.ResourceSetName);
query = item.ApplyTo(query);

Expand Down
49 changes: 1 addition & 48 deletions src/Microsoft.Restier.Publishers.OData/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,22 +164,6 @@ public static bool IsConcurrencyCheckEnabled(this IEdmModel model, IEdmEntitySet
return propertiesAttributes;
}

public static Type GetClrType(this IEdmType edmType, ApiBase api)
{
IEdmModel edmModel = api.GetModelAsync().Result;

ClrTypeAnnotation annotation = edmModel.GetAnnotationValue<ClrTypeAnnotation>(edmType);
if (annotation != null)
{
return annotation.ClrType;
}

throw new NotSupportedException(string.Format(
CultureInfo.InvariantCulture,
Resources.ElementTypeNotFound,
edmType.FullTypeName()));
}

public static IEdmTypeReference GetReturnTypeReference(this Type type, IEdmModel model)
{
// In case it is a nullable type, get the underlying type
Expand All @@ -196,38 +180,7 @@ public static IEdmTypeReference GetReturnTypeReference(this Type type, IEdmModel
type = typeof(void);
}

return GetTypeReference(type, model);
}

public static IEdmTypeReference GetTypeReference(this Type type, IEdmModel model)
{
Type elementType;
if (type.TryGetElementType(out elementType))
{
return EdmCoreModel.GetCollection(GetTypeReference(elementType, model));
}

var edmType = model.FindDeclaredType(type.FullName);

var enumType = edmType as IEdmEnumType;
if (enumType != null)
{
return new EdmEnumTypeReference(enumType, true);
}

var complexType = edmType as IEdmComplexType;
if (complexType != null)
{
return new EdmComplexTypeReference(complexType, true);
}

var entityType = edmType as IEdmEntityType;
if (entityType != null)
{
return new EdmEntityTypeReference(entityType, true);
}

return type.GetPrimitiveTypeReference();
return EdmHelpers.GetTypeReference(type, model);
}

public static bool IsSameTerm(this IEdmTerm sourceTerm, IEdmTerm targetTerm)
Expand Down
112 changes: 93 additions & 19 deletions src/Microsoft.Restier.Publishers.OData/Model/EdmHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,105 @@
using System;
using System.Globalization;
using System.Linq;
using System.Web.OData;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OData.Edm;

namespace Microsoft.Restier.Publishers.OData.Model
{
internal static class EdmHelpers
/// <summary>
/// This class contains some common extension methods for Edm
/// </summary>
public static class EdmHelpers
{
private const string DefaultEntityContainerName = "DefaultContainer";

public static EdmEntityContainer EnsureEntityContainer(this EdmModel model, Type apiType)
/// <summary>
/// The type to get the primitive type reference
/// </summary>
/// <param name="type">The clr type to get edm type reference</param>
/// <returns>The edm type reference for the clr type</returns>
public static EdmTypeReference GetPrimitiveTypeReference(this Type type)
{
// Only handle primitive type right now
bool isNullable;
EdmPrimitiveTypeKind? primitiveTypeKind = EdmHelpers.GetPrimitiveTypeKind(type, out isNullable);

if (!primitiveTypeKind.HasValue)
{
return null;
}

return new EdmPrimitiveTypeReference(
EdmCoreModel.Instance.GetPrimitiveType(primitiveTypeKind.Value),
isNullable);
}

/// <summary>
/// Get the clr type for a specified edm type
/// </summary>
/// <param name="edmType">The edm type to get clr type</param>
/// <param name="serviceProvider">The provider to get service from DI container</param>
/// <returns>The clr type</returns>
public static Type GetClrType(this IEdmType edmType, IServiceProvider serviceProvider)
{
IEdmModel edmModel = serviceProvider.GetService<IEdmModel>();

ClrTypeAnnotation annotation = edmModel.GetAnnotationValue<ClrTypeAnnotation>(edmType);
if (annotation != null)
{
return annotation.ClrType;
}

throw new NotSupportedException(string.Format(
CultureInfo.InvariantCulture,
Resources.ElementTypeNotFound,
edmType.FullTypeName()));
}

/// <summary>
/// Get the edm type reference for a clr type
/// </summary>
/// <param name="type">The clr type</param>
/// <param name="model">The Edm model</param>
/// <returns>The Edm type reference</returns>
public static IEdmTypeReference GetTypeReference(this Type type, IEdmModel model)
{
if (type == null || model == null)
{
return null;
}

Type elementType;
if (type.TryGetElementType(out elementType))
{
return EdmCoreModel.GetCollection(GetTypeReference(elementType, model));
}

var edmType = model.FindDeclaredType(type.FullName);

var enumType = edmType as IEdmEnumType;
if (enumType != null)
{
return new EdmEnumTypeReference(enumType, true);
}

var complexType = edmType as IEdmComplexType;
if (complexType != null)
{
return new EdmComplexTypeReference(complexType, true);
}

var entityType = edmType as IEdmEntityType;
if (entityType != null)
{
return new EdmEntityTypeReference(entityType, true);
}

return type.GetPrimitiveTypeReference();
}

internal static EdmEntityContainer EnsureEntityContainer(this EdmModel model, Type apiType)
{
var container = (EdmEntityContainer)model.EntityContainer;
if (container == null)
Expand All @@ -24,7 +114,7 @@ public static EdmEntityContainer EnsureEntityContainer(this EdmModel model, Type
return container;
}

public static IEdmEntitySet FindDeclaredEntitySetByTypeReference(
internal static IEdmEntitySet FindDeclaredEntitySetByTypeReference(
this IEdmModel model, IEdmTypeReference typeReference)
{
IEdmTypeReference elementTypeReference;
Expand All @@ -42,22 +132,6 @@ public static EdmEntityContainer EnsureEntityContainer(this EdmModel model, Type
.SingleOrDefault(e => e.EntityType().FullTypeName() == elementTypeReference.FullName());
}

public static EdmTypeReference GetPrimitiveTypeReference(this Type type)
{
// Only handle primitive type right now
bool isNullable;
EdmPrimitiveTypeKind? primitiveTypeKind = EdmHelpers.GetPrimitiveTypeKind(type, out isNullable);

if (!primitiveTypeKind.HasValue)
{
return null;
}

return new EdmPrimitiveTypeReference(
EdmCoreModel.Instance.GetPrimitiveType(primitiveTypeKind.Value),
isNullable);
}

private static bool TryGetElementTypeReference(
this IEdmTypeReference typeReference, out IEdmTypeReference elementTypeReference)
{
Expand Down