Skip to content

Commit

Permalink
Unify way of loading assemblies for getting types.
Browse files Browse the repository at this point in the history
Add assemblies resolver injection.
Move IAssembliesResolver property to the class where is being used.
Add test for assemblies resolver injection.
Update NewtonSoftJson version in Sample and Test projects.
Fix accesibility of methods and other minor changes
  • Loading branch information
Javier Garrido committed Apr 28, 2017
1 parent ef9084d commit 1fb3ed0
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 48 deletions.
7 changes: 5 additions & 2 deletions Swashbuckle.OData.Sample/App_Start/SwaggerConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,11 @@ public static void Register()
//
odataConfig.IncludeNavigationProperties();

// Enable Caché for swagger doc requests
odataConfig.EnableSwaggerRequestCaching();
// Enable Cache for swagger doc requests
odataConfig.EnableSwaggerRequestCaching();

//Set custom AssembliesResolver
odataConfig.SetAssembliesResolver(new Utils.CustomAssembliesResolver());
}));
})
.EnableSwaggerUi(c =>
Expand Down
5 changes: 3 additions & 2 deletions Swashbuckle.OData.Sample/Swashbuckle.OData.Sample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Swashbuckle.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cd1bb07a5ac7c7bc, processorArchitecture=MSIL">
Expand Down Expand Up @@ -171,6 +171,7 @@
<Compile Include="Repositories\SwashbuckleODataContext.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Repositories\TestDbSet.cs" />
<Compile Include="Utils\CustomAssembliesResolver.cs" />
<Compile Include="Utils\SequentialGuidGenerator.cs" />
<Compile Include="Versioning\ModelValidationFilterAttribute.cs" />
<Compile Include="Versioning\ODataHelper.cs" />
Expand Down
18 changes: 18 additions & 0 deletions Swashbuckle.OData.Sample/Utils/CustomAssembliesResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Collections.Generic;
using System.Reflection;
using System.Web.Http.Dispatcher;

namespace SwashbuckleODataSample.Utils
{
/// <summary>
/// Custom Assemblies Resolver, using the default assemblies resolver, only for demonstration purposes
/// </summary>
public class CustomAssembliesResolver : DefaultAssembliesResolver
{
public override ICollection<Assembly> GetAssemblies()
{
ICollection<Assembly> baseAssemblies = base.GetAssemblies();
return baseAssemblies;
}
}
}
2 changes: 1 addition & 1 deletion Swashbuckle.OData.Sample/Web.config
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
<bindingRedirect oldVersion="0.0.0.0-7.0.0.0" newVersion="7.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
Expand Down
2 changes: 1 addition & 1 deletion Swashbuckle.OData.Sample/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<package id="Microsoft.Restier.Publishers.OData" version="1.0.0-beta" targetFramework="net452" />
<package id="Microsoft.Spatial" version="7.0.0" targetFramework="net452" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net452" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net452" />
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net452" />
<package id="Swashbuckle" version="5.5.3" targetFramework="net452" />
<package id="Swashbuckle.Core" version="5.5.3" targetFramework="net452" />
<package id="WebActivatorEx" version="2.1.0" targetFramework="net452" />
Expand Down
47 changes: 47 additions & 0 deletions Swashbuckle.OData.Tests/Fixtures/ODataSwaggerProviderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
using SwashbuckleODataSample.ApiControllers;
using SwashbuckleODataSample.Models;
using SwashbuckleODataSample.ODataControllers;
using System.Collections.Generic;
using System.Reflection;

namespace Swashbuckle.OData.Tests
{
Expand Down Expand Up @@ -161,16 +163,59 @@ public async Task It_supports_caching_swagger_document()

// First request (Non-cached)
var swaggerDocument = await httpClient.GetJsonAsync<SwaggerDocument>("swagger/docs/v1");
swaggerDocument.Should().NotBeNull();

//Cached request
var swaggerDocument2 = await httpClient.GetJsonAsync<SwaggerDocument>("swagger/docs/v1");
swaggerDocument2.Should().NotBeNull();

swaggerDocument.ShouldBeEquivalentTo(swaggerDocument2);

await ValidationUtils.ValidateSwaggerJson();

}
}

/// <summary>
/// Test to check if the custom assemblies resolver injection works
/// </summary>
/// <returns></returns>
[Test]
public async Task It_supports_a_custom_assemblies_resolver()
{
SwaggerDocument customAssembliesResolverSwaggerDoc;
SwaggerDocument defaultAssembliesResolverSwaggerDoc;

Action<ODataSwaggerDocsConfig> config = c => c.SetAssembliesResolver(new TestAssembliesResolver());
using (WebApp.Start(HttpClientUtils.BaseAddress, appBuilder =>
Configuration(appBuilder,odataSwaggerDocsConfig: config)))
{
var httpClient = HttpClientUtils.GetHttpClient(HttpClientUtils.BaseAddress);
customAssembliesResolverSwaggerDoc = await httpClient.GetJsonAsync<SwaggerDocument>("swagger/docs/v1");
customAssembliesResolverSwaggerDoc.Should().NotBeNull();

await ValidationUtils.ValidateSwaggerJson();
}

using (WebApp.Start(HttpClientUtils.BaseAddress, builder => Configuration(builder)))
{
var httpClient = HttpClientUtils.GetHttpClient(HttpClientUtils.BaseAddress);
defaultAssembliesResolverSwaggerDoc = await httpClient.GetJsonAsync<SwaggerDocument>("swagger/docs/v1");
customAssembliesResolverSwaggerDoc.Should().NotBeNull();
}

customAssembliesResolverSwaggerDoc.ShouldBeEquivalentTo(defaultAssembliesResolverSwaggerDoc);

}

private class TestAssembliesResolver : DefaultAssembliesResolver
{
public override ICollection<Assembly> GetAssemblies()
{
ICollection<Assembly> baseAssemblies = base.GetAssemblies();
return baseAssemblies;
}
}

private static void Configuration(IAppBuilder appBuilder, Type targetController = null, Action<SwaggerDocsConfig> swaggerDocsConfig = null, Action<ODataSwaggerDocsConfig> odataSwaggerDocsConfig = null)
{
Expand Down Expand Up @@ -216,5 +261,7 @@ private static IEdmModel GetFakeModel()
builder.EntitySet<Customer>("FakeCustomers");
return builder.GetEdmModel();
}

}

}
8 changes: 5 additions & 3 deletions Swashbuckle.OData.Tests/Swashbuckle.OData.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@
<HintPath>..\packages\Microsoft.Spatial.7.0.0\lib\portable-net45+win8+wpa81\Microsoft.Spatial.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json.Schema, Version=1.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
Expand Down Expand Up @@ -199,7 +199,9 @@
<Compile Include="ValidationUtils.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="app.config">
<SubType>Designer</SubType>
</None>
<None Include="schema-draft-v4.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
2 changes: 1 addition & 1 deletion Swashbuckle.OData.Tests/app.config
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.0.0.0" newVersion="7.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
Expand Down
2 changes: 1 addition & 1 deletion Swashbuckle.OData.Tests/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<package id="Microsoft.Restier.Providers.EntityFramework" version="1.0.0-beta" targetFramework="net452" />
<package id="Microsoft.Restier.Publishers.OData" version="1.0.0-beta" targetFramework="net452" />
<package id="Microsoft.Spatial" version="7.0.0" targetFramework="net452" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net452" />
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net452" />
<package id="Newtonsoft.Json.Schema" version="1.0.11" targetFramework="net452" />
<package id="NUnit" version="2.6.4" targetFramework="net452" />
<package id="NUnit.Runners" version="2.6.4" targetFramework="net452" />
Expand Down
30 changes: 9 additions & 21 deletions Swashbuckle.OData/Descriptions/EdmLibHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,15 @@
using System.Globalization;
using System.IO;
using System.Linq;
using System.Web.Http.Dispatcher;
using Microsoft.OData.Edm;
using Microsoft.Spatial;

namespace System.Web.OData.Formatter
{
internal static class EdmLibHelpers
{
private static readonly EdmCoreModel CoreModel = EdmCoreModel.Instance;

private static readonly IAssembliesResolver DefaultAssemblyResolver = new DefaultAssembliesResolver();

private static readonly EdmCoreModel CoreModel = EdmCoreModel.Instance;

private static readonly Dictionary<Type, IEdmPrimitiveType> BuiltInTypesMapping = new[]
{
new KeyValuePair<Type, IEdmPrimitiveType>(typeof (string), GetPrimitiveType(EdmPrimitiveTypeKind.String)),
Expand Down Expand Up @@ -214,15 +211,9 @@ public static IEdmTypeReference ToEdmTypeReference(this IEdmType edmType, bool i
}

public static Type GetClrType(IEdmTypeReference edmTypeReference, IEdmModel edmModel)
{
return GetClrType(edmTypeReference, edmModel, DefaultAssemblyResolver);
}

public static Type GetClrType(IEdmTypeReference edmTypeReference, IEdmModel edmModel, IAssembliesResolver assembliesResolver)
{
Contract.Requires(edmTypeReference != null);
Contract.Requires(edmModel != null);
Contract.Requires(assembliesResolver != null);

var primitiveClrType = BuiltInTypesMapping.Where(kvp => edmTypeReference.GetDefinition().IsEquivalentTo(kvp.Value) && (!edmTypeReference.IsNullable || IsNullable(kvp.Key))).Select(kvp => kvp.Key).FirstOrDefault();

Expand All @@ -232,7 +223,7 @@ public static Type GetClrType(IEdmTypeReference edmTypeReference, IEdmModel edmM
}
var edmType = edmTypeReference.GetDefinition();
Contract.Assume(edmType is IEdmSchemaType);
var clrType = GetClrType(edmType, edmModel, assembliesResolver);
var clrType = GetClrType(edmType, edmModel);
if (clrType != null && clrType.IsEnum && edmTypeReference.IsNullable)
{
return clrType.ToNullable();
Expand All @@ -241,11 +232,10 @@ public static Type GetClrType(IEdmTypeReference edmTypeReference, IEdmModel edmM
return clrType;
}

public static Type GetClrType(IEdmType edmType, IEdmModel edmModel, IAssembliesResolver assembliesResolver)
public static Type GetClrType(IEdmType edmType, IEdmModel edmModel)
{
Contract.Requires(edmType is IEdmSchemaType);
Contract.Requires(edmModel != null);
Contract.Requires(assembliesResolver != null);

var edmSchemaType = (IEdmSchemaType) edmType;

Expand All @@ -256,7 +246,7 @@ public static Type GetClrType(IEdmType edmType, IEdmModel edmModel, IAssembliesR
}

var typeName = edmSchemaType.FullName();
var matchingTypes = GetMatchingTypes(typeName, assembliesResolver);
var matchingTypes = GetMatchingTypes(typeName);

var matchingTypesList = matchingTypes as IList<Type> ?? matchingTypes.ToList();
if (matchingTypesList.Count > 1)
Expand Down Expand Up @@ -321,12 +311,10 @@ private static Type ExtractGenericInterface(Type queryType, Type interfaceType)
Func<Type, bool> matchesInterface = t => t.IsGenericType && t.GetGenericTypeDefinition() == interfaceType;
return matchesInterface(queryType) ? queryType : queryType.GetInterfaces().FirstOrDefault(matchesInterface);
}

private static IEnumerable<Type> GetMatchingTypes(string edmFullName, IAssembliesResolver assembliesResolver)
{
Contract.Requires(assembliesResolver != null);

return TypeHelper.GetLoadedTypes(assembliesResolver).Where(t => t.IsPublic && t.EdmFullName() == edmFullName);

private static IEnumerable<Type> GetMatchingTypes(string edmFullName)
{
return TypeHelper.GetLoadedTypes().Where(t => t.IsPublic && t.EdmFullName() == edmFullName);
}

// TODO (workitem 336): Support nested types and anonymous types.
Expand Down
36 changes: 21 additions & 15 deletions Swashbuckle.OData/Descriptions/TypeHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ namespace System.Web.OData
{
internal static class TypeHelper
{
public static Type ToNullable(this Type t)
private static IAssembliesResolver _assembliesResolver = new DefaultAssembliesResolver();

internal static Type ToNullable(this Type t)
{
Contract.Requires(t != null);

Expand All @@ -26,7 +28,7 @@ public static Type ToNullable(this Type t)
}

// Gets the collection element type.
public static Type GetInnerElementType(this Type type)
internal static Type GetInnerElementType(this Type type)
{
Contract.Requires(type != null);

Expand All @@ -37,15 +39,15 @@ public static Type GetInnerElementType(this Type type)
return elementType;
}

public static bool IsCollection(this Type type)
internal static bool IsCollection(this Type type)
{
Contract.Requires(type != null);

Type elementType;
return type.IsCollection(out elementType);
}

public static bool IsCollection(this Type type, out Type elementType)
internal static bool IsCollection(this Type type, out Type elementType)
{
Contract.Requires(type != null);
Contract.Ensures(Contract.ValueAtReturn(out elementType) != null);
Expand Down Expand Up @@ -74,21 +76,30 @@ public static bool IsCollection(this Type type, out Type elementType)
return false;
}

public static Type GetUnderlyingTypeOrSelf(Type type)
internal static Type GetUnderlyingTypeOrSelf(Type type)
{
Contract.Requires(type != null);

return Nullable.GetUnderlyingType(type) ?? type;
}

public static bool IsEnum(Type type)
internal static bool IsEnum(Type type)
{
Contract.Requires(type != null);

var underlyingTypeOrSelf = GetUnderlyingTypeOrSelf(type);
return underlyingTypeOrSelf.IsEnum;
}

/// <summary>
/// Set the custom Assemblies Resolver to be used instead of using the default one
/// </summary>
/// <param name="assembliesResolver"></param>
internal static void SetAssembliesResolver(IAssembliesResolver assembliesResolver)
{
_assembliesResolver = assembliesResolver;
}

/// <summary>
/// Determines whether the given type is a primitive type or
/// is a <see cref="string" />, <see cref="DateTime" />, <see cref="Decimal" />,
Expand Down Expand Up @@ -165,14 +176,12 @@ internal static Type GetImplementedIEnumerableType(Type type)

[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Catching all exceptions in this case is the right to do.")]
// This code is copied from DefaultHttpControllerTypeResolver.GetControllerTypes.
internal static IEnumerable<Type> GetLoadedTypes(IAssembliesResolver assembliesResolver)
internal static IEnumerable<Type> GetLoadedTypes()
{
Contract.Requires(assembliesResolver != null);

var result = new List<Type>();

// Go through all assemblies referenced by the application and search for types matching a predicate
var assemblies = assembliesResolver.GetAssemblies();
var assemblies = _assembliesResolver.GetAssemblies();
Contract.Assume(assemblies != null);
foreach (var assembly in assemblies)
{
Expand Down Expand Up @@ -230,12 +239,9 @@ private static Type GetInnerGenericType(Type interfaceType)
/// <returns>
/// The <see cref="Type"/> found; null if not found.
/// </returns>
public static Type FindType(string fullName)
internal static Type FindType(string fullName)
{
return
AppDomain.CurrentDomain.GetAssemblies()
.Where(a => !a.IsDynamic)
.SelectMany(a => a.GetTypes())
return GetLoadedTypes()
.First(t => t.FullName.Equals(fullName));
}
}
Expand Down
Loading

0 comments on commit 1fb3ed0

Please sign in to comment.