diff --git a/build/assets.msbuildproj b/build/assets.msbuildproj
index 8d3dba2a..0ae99dc5 100644
--- a/build/assets.msbuildproj
+++ b/build/assets.msbuildproj
@@ -2,6 +2,7 @@
netstandard1.0
false
+ $(NoWarn);NETSDK1215
diff --git a/src/Abstractions/src/Asp.Versioning.Abstractions/Asp.Versioning.Abstractions.csproj b/src/Abstractions/src/Asp.Versioning.Abstractions/Asp.Versioning.Abstractions.csproj
index 68dd7991..861b642c 100644
--- a/src/Abstractions/src/Asp.Versioning.Abstractions/Asp.Versioning.Abstractions.csproj
+++ b/src/Abstractions/src/Asp.Versioning.Abstractions/Asp.Versioning.Abstractions.csproj
@@ -14,6 +14,10 @@
true
+
+ false
+
+
diff --git a/src/AspNetCore/OData/src/Asp.Versioning.OData.ApiExplorer/ApiExplorer/PartialODataDescriptionProvider.cs b/src/AspNetCore/OData/src/Asp.Versioning.OData.ApiExplorer/ApiExplorer/PartialODataDescriptionProvider.cs
index 47eac901..4099958b 100644
--- a/src/AspNetCore/OData/src/Asp.Versioning.OData.ApiExplorer/ApiExplorer/PartialODataDescriptionProvider.cs
+++ b/src/AspNetCore/OData/src/Asp.Versioning.OData.ApiExplorer/ApiExplorer/PartialODataDescriptionProvider.cs
@@ -201,6 +201,8 @@ public ModelMetadata GetMetadataForType( Type modelType ) =>
throw new NotImplementedException();
}
+ [UnconditionalSuppressMessage( "ILLink", "IL2092" )]
+ [UnconditionalSuppressMessage( "ILLink", "IL2093" )]
private sealed class StubModelTypeBuilder : IModelTypeBuilder
{
public Type NewActionParameters( IEdmModel model, IEdmAction action, string controllerName, ApiVersion apiVersion ) =>
diff --git a/src/AspNetCore/OData/src/Asp.Versioning.OData.ApiExplorer/Asp.Versioning.OData.ApiExplorer.csproj b/src/AspNetCore/OData/src/Asp.Versioning.OData.ApiExplorer/Asp.Versioning.OData.ApiExplorer.csproj
index a443fa16..bf0661c6 100644
--- a/src/AspNetCore/OData/src/Asp.Versioning.OData.ApiExplorer/Asp.Versioning.OData.ApiExplorer.csproj
+++ b/src/AspNetCore/OData/src/Asp.Versioning.OData.ApiExplorer/Asp.Versioning.OData.ApiExplorer.csproj
@@ -8,6 +8,7 @@
ASP.NET Core API Versioning API Explorer for OData v4.0
The API Explorer extensions for ASP.NET Core API Versioning and OData v4.0.
Asp;AspNet;AspNetCore;Versioning;ApiExplorer;OData
+ true
diff --git a/src/AspNetCore/OData/src/Asp.Versioning.OData/Asp.Versioning.OData.csproj b/src/AspNetCore/OData/src/Asp.Versioning.OData/Asp.Versioning.OData.csproj
index e69c80d7..64df816f 100644
--- a/src/AspNetCore/OData/src/Asp.Versioning.OData/Asp.Versioning.OData.csproj
+++ b/src/AspNetCore/OData/src/Asp.Versioning.OData/Asp.Versioning.OData.csproj
@@ -8,6 +8,7 @@
ASP.NET Core API Versioning with OData v4.0
A service API versioning library for Microsoft ASP.NET Core with OData v4.0.
Asp;AspNet;AspNetCore;Versioning;OData
+ true
diff --git a/src/AspNetCore/OData/src/Asp.Versioning.OData/DependencyInjection/IServiceCollectionExtensions.cs b/src/AspNetCore/OData/src/Asp.Versioning.OData/DependencyInjection/IServiceCollectionExtensions.cs
index 16432665..0f17e2eb 100644
--- a/src/AspNetCore/OData/src/Asp.Versioning.OData/DependencyInjection/IServiceCollectionExtensions.cs
+++ b/src/AspNetCore/OData/src/Asp.Versioning.OData/DependencyInjection/IServiceCollectionExtensions.cs
@@ -31,6 +31,7 @@ internal static ApplicationPartManager GetOrCreateApplicationPartManager( this I
return partManager;
}
+ [UnconditionalSuppressMessage( "ILLink", "IL2072", Justification = "Model configuration types are never trimmed" )]
internal static void AddModelConfigurationsAsServices( this IServiceCollection services, ApplicationPartManager partManager )
{
var feature = new ModelConfigurationFeature();
diff --git a/src/AspNetCore/OData/src/Asp.Versioning.OData/OData/ODataMultiModelApplicationModelProvider.cs b/src/AspNetCore/OData/src/Asp.Versioning.OData/OData/ODataMultiModelApplicationModelProvider.cs
index cc798280..5676e28f 100644
--- a/src/AspNetCore/OData/src/Asp.Versioning.OData/OData/ODataMultiModelApplicationModelProvider.cs
+++ b/src/AspNetCore/OData/src/Asp.Versioning.OData/OData/ODataMultiModelApplicationModelProvider.cs
@@ -135,7 +135,8 @@ private static Type GetDefaultApplicationModelProviderType()
return Type.GetType( $"{TypeName}, {assemblyName}", throwOnError: true, ignoreCase: false )!;
}
- private static Func, IApplicationModelProvider> CreateActivator( Type type )
+ private static Func, IApplicationModelProvider> CreateActivator(
+ [DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.PublicConstructors )] Type type )
{
var options = Parameter( typeof( IOptions ), "options" );
var @new = New( type.GetConstructors()[0], options );
diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc.ApiExplorer/ApiExplorerOptionsFactory{T}.cs b/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc.ApiExplorer/ApiExplorerOptionsFactory{T}.cs
index 1a79e0a3..6c94a430 100644
--- a/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc.ApiExplorer/ApiExplorerOptionsFactory{T}.cs
+++ b/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc.ApiExplorer/ApiExplorerOptionsFactory{T}.cs
@@ -3,13 +3,15 @@
namespace Asp.Versioning.ApiExplorer;
using Microsoft.Extensions.Options;
+using static System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes;
///
/// Represents a factory to create API explorer options.
///
/// The type of options to create.
[CLSCompliant( false )]
-public class ApiExplorerOptionsFactory : OptionsFactory where T : ApiExplorerOptions
+public class ApiExplorerOptionsFactory<[DynamicallyAccessedMembers( PublicParameterlessConstructor )] T>
+ : OptionsFactory where T : ApiExplorerOptions
{
private readonly IOptions optionsHolder;
diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc.ApiExplorer/Asp.Versioning.Mvc.ApiExplorer.csproj b/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc.ApiExplorer/Asp.Versioning.Mvc.ApiExplorer.csproj
index 528a203a..5845752b 100644
--- a/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc.ApiExplorer/Asp.Versioning.Mvc.ApiExplorer.csproj
+++ b/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc.ApiExplorer/Asp.Versioning.Mvc.ApiExplorer.csproj
@@ -8,6 +8,7 @@
ASP.NET Core API Versioning API Explorer
The API Explorer extensions for ASP.NET Core API Versioning.
Asp;AspNet;AspNetCore;Versioning;ApiExplorer
+ true
diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc/Asp.Versioning.Mvc.csproj b/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc/Asp.Versioning.Mvc.csproj
index 52963338..21ca9fe8 100644
--- a/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc/Asp.Versioning.Mvc.csproj
+++ b/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc/Asp.Versioning.Mvc.csproj
@@ -9,6 +9,7 @@
A service API versioning library for Microsoft ASP.NET Core MVC.
Asp;AspNet;AspNetCore;MVC;Versioning
true
+ true
diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc/DependencyInjection/IApiVersioningBuilderExtensions.cs b/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc/DependencyInjection/IApiVersioningBuilderExtensions.cs
index eef6b507..21e66163 100644
--- a/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc/DependencyInjection/IApiVersioningBuilderExtensions.cs
+++ b/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc/DependencyInjection/IApiVersioningBuilderExtensions.cs
@@ -16,6 +16,7 @@ namespace Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Runtime.CompilerServices;
using static ServiceDescriptor;
+using static System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes;
///
/// Provides ASP.NET Core MVC specific extension methods for .
@@ -85,7 +86,11 @@ private static object CreateInstance( this IServiceProvider services, ServiceDes
return ActivatorUtilities.GetServiceOrCreateInstance( services, descriptor.ImplementationType! );
}
- private static void TryReplace( this IServiceCollection services )
+ private static void TryReplace<
+ TService,
+ TImplementation,
+ [DynamicallyAccessedMembers( NonPublicConstructors | PublicConstructors )]
+ TReplacement>( this IServiceCollection services )
{
var serviceType = typeof( TService );
var implementationType = typeof( TImplementation );
diff --git a/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc/Routing/ApiVersionUrlHelper.cs b/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc/Routing/ApiVersionUrlHelper.cs
index bbf03793..bd3e398e 100644
--- a/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc/Routing/ApiVersionUrlHelper.cs
+++ b/src/AspNetCore/WebApi/src/Asp.Versioning.Mvc/Routing/ApiVersionUrlHelper.cs
@@ -98,9 +98,30 @@ public ApiVersionUrlHelper( ActionContext actionContext, IUrlHelper url )
return current;
}
- if ( current is not RouteValueDictionary values )
+ RouteValueDictionary values;
+
+ if ( current is null )
+ {
+ values = new() { { key, value } };
+ return values;
+ }
+
+ if ( current is RouteValueDictionary dictionary )
+ {
+ values = dictionary;
+ }
+ else if ( current is IEnumerable> kvps )
{
- values = current == null ? new() : new( current );
+ values = [];
+
+ foreach ( var kvp in kvps )
+ {
+ values.Add( kvp.Key, kvp.Value );
+ }
+ }
+ else
+ {
+ return current;
}
if ( !values.ContainsKey( key ) )
diff --git a/src/Client/src/Asp.Versioning.Http.Client/Asp.Versioning.Http.Client.csproj b/src/Client/src/Asp.Versioning.Http.Client/Asp.Versioning.Http.Client.csproj
index b704593d..08fc140f 100644
--- a/src/Client/src/Asp.Versioning.Http.Client/Asp.Versioning.Http.Client.csproj
+++ b/src/Client/src/Asp.Versioning.Http.Client/Asp.Versioning.Http.Client.csproj
@@ -14,6 +14,10 @@
true
+
+ false
+
+
diff --git a/src/Common/src/Common.Backport/Common.Backport.msbuildproj b/src/Common/src/Common.Backport/Common.Backport.msbuildproj
index 9dd66e3a..0da069a9 100644
--- a/src/Common/src/Common.Backport/Common.Backport.msbuildproj
+++ b/src/Common/src/Common.Backport/Common.Backport.msbuildproj
@@ -1,6 +1,7 @@
netstandard1.0
+ $(NoWarn);NETSDK1215
diff --git a/src/Common/src/Common.Mvc/Conventions/ActionConventionBuilderExtensions.cs b/src/Common/src/Common.Mvc/Conventions/ActionConventionBuilderExtensions.cs
index 98cb8aa3..63464548 100644
--- a/src/Common/src/Common.Mvc/Conventions/ActionConventionBuilderExtensions.cs
+++ b/src/Common/src/Common.Mvc/Conventions/ActionConventionBuilderExtensions.cs
@@ -73,6 +73,9 @@ public static IActionConventionBuilder Action
/// If there is only one corresponding match found, then the argument types are ignored;
/// otherwise, the argument types are used for method overload resolution. Action
/// methods that have the applied will also be ignored.
+#if !NETFRAMEWORK
+ [UnconditionalSuppressMessage( "ILLink", "IL2072", Justification = "Controller types are never trimmed" )]
+#endif
public static IActionConventionBuilder Action( this IActionConventionBuilder builder, string methodName, params Type[] argumentTypes )
{
ArgumentNullException.ThrowIfNull( builder );
diff --git a/src/Common/src/Common.Mvc/Conventions/ActionMethodResolver.cs b/src/Common/src/Common.Mvc/Conventions/ActionMethodResolver.cs
index 3c0fa420..8feb6bfd 100644
--- a/src/Common/src/Common.Mvc/Conventions/ActionMethodResolver.cs
+++ b/src/Common/src/Common.Mvc/Conventions/ActionMethodResolver.cs
@@ -10,12 +10,19 @@ namespace Asp.Versioning.Conventions;
#if NETFRAMEWORK
using System.Web.Http;
#endif
+using static System.Reflection.BindingFlags;
internal static class ActionMethodResolver
{
- internal static MethodInfo Resolve( Type controllerType, string methodName, Type[] argumentTypes )
+ internal static MethodInfo Resolve(
+#if !NETFRAMEWORK
+ [DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.PublicMethods )]
+#endif
+ Type controllerType,
+ string methodName,
+ Type[] argumentTypes )
{
- var methods = controllerType.GetRuntimeMethods().Where( m => m.Name == methodName && IsAction( m ) ).ToArray();
+ var methods = controllerType.GetMethods( Instance | Public ).Where( m => m.Name == methodName && IsAction( m ) ).ToArray();
switch ( methods.Length )
{
diff --git a/src/Common/src/Common.Mvc/Conventions/ControllerConventionBuilderExtensions.cs b/src/Common/src/Common.Mvc/Conventions/ControllerConventionBuilderExtensions.cs
index 328b8b70..47e7a491 100644
--- a/src/Common/src/Common.Mvc/Conventions/ControllerConventionBuilderExtensions.cs
+++ b/src/Common/src/Common.Mvc/Conventions/ControllerConventionBuilderExtensions.cs
@@ -73,6 +73,9 @@ public static IActionConventionBuilder Action
/// If there is only one corresponding match found, then the argument types are ignored;
/// otherwise, the argument types are used for method overload resolution. Action
/// methods that have the applied will also be ignored.
+#if !NETFRAMEWORK
+ [UnconditionalSuppressMessage( "ILLink", "IL2072", Justification = "Controller types are never trimmed" )]
+#endif
public static IActionConventionBuilder Action( this IControllerConventionBuilder builder, string methodName, params Type[] argumentTypes )
{
ArgumentNullException.ThrowIfNull( builder );
diff --git a/src/Common/src/Common.OData.ApiExplorer/Conventions/ODataActionQueryOptionsConventionBuilderExtensions.cs b/src/Common/src/Common.OData.ApiExplorer/Conventions/ODataActionQueryOptionsConventionBuilderExtensions.cs
index bcd941a0..33ab2471 100644
--- a/src/Common/src/Common.OData.ApiExplorer/Conventions/ODataActionQueryOptionsConventionBuilderExtensions.cs
+++ b/src/Common/src/Common.OData.ApiExplorer/Conventions/ODataActionQueryOptionsConventionBuilderExtensions.cs
@@ -16,6 +16,7 @@ namespace Asp.Versioning.Conventions;
using System.Web.Http;
using System.Web.Http.Controllers;
#endif
+using static System.Reflection.BindingFlags;
///
/// Provides extension methods for the
@@ -187,6 +188,9 @@ public static ODataActionQueryOptionsConventionBuilder Actionargument types are ignored;
/// otherwise, the argument types are used for method overload resolution. Action
/// methods that have the applied will also be ignored.
+#if !NETFRAMEWORK
+ [UnconditionalSuppressMessage( "ILLink", "IL2075", Justification = "Controller types and actions are never trimmed" )]
+#endif
public static ODataActionQueryOptionsConventionBuilder Action(
this IODataActionQueryOptionsConventionBuilder builder,
string methodName,
@@ -197,7 +201,7 @@ public static ODataActionQueryOptionsConventionBuilder Action(
string message;
var methods = builder.ControllerType
- .GetRuntimeMethods()
+ .GetMethods( Instance | Public )
.Where( m => m.Name == methodName && IsAction( m ) )
.ToArray();
diff --git a/src/Common/src/Common.OData.ApiExplorer/Microsoft.OData.Edm/EdmExtensions.cs b/src/Common/src/Common.OData.ApiExplorer/Microsoft.OData.Edm/EdmExtensions.cs
index 16ef9c9c..f9c60670 100644
--- a/src/Common/src/Common.OData.ApiExplorer/Microsoft.OData.Edm/EdmExtensions.cs
+++ b/src/Common/src/Common.OData.ApiExplorer/Microsoft.OData.Edm/EdmExtensions.cs
@@ -37,6 +37,9 @@ internal static class EdmExtensions
return null;
}
+#if !NETFRAMEWORK
+ [UnconditionalSuppressMessage( "ILLink", "IL2057", Justification = "The types being referenced are well-known and will not be trimmed." )]
+#endif
private static Type? DeriveFromWellKnowPrimitive( string edmFullName ) => edmFullName switch
{
"Edm.String" or "Edm.Byte" or "Edm.SByte" or "Edm.Int16" or "Edm.Int32" or "Edm.Int64" or
diff --git a/src/Common/src/Common.OData.ApiExplorer/OData/ClassProperty.cs b/src/Common/src/Common.OData.ApiExplorer/OData/ClassProperty.cs
index 98784a2f..f5959f92 100644
--- a/src/Common/src/Common.OData.ApiExplorer/OData/ClassProperty.cs
+++ b/src/Common/src/Common.OData.ApiExplorer/OData/ClassProperty.cs
@@ -21,6 +21,9 @@ internal ClassProperty( PropertyInfo clrProperty, Type propertyType )
Attributes = clrProperty.DeclaredAttributes().ToArray();
}
+#if !NETFRAMEWORK
+ [UnconditionalSuppressMessage( "ILLink", "IL2072" )]
+#endif
internal ClassProperty( IEdmOperationParameter parameter, TypeSubstitutionContext context )
{
Name = parameter.Name;
diff --git a/src/Common/src/Common.OData.ApiExplorer/OData/DefaultModelTypeBuilder.cs b/src/Common/src/Common.OData.ApiExplorer/OData/DefaultModelTypeBuilder.cs
index f8a836ec..76fec0ff 100644
--- a/src/Common/src/Common.OData.ApiExplorer/OData/DefaultModelTypeBuilder.cs
+++ b/src/Common/src/Common.OData.ApiExplorer/OData/DefaultModelTypeBuilder.cs
@@ -14,6 +14,9 @@ namespace Asp.Versioning.OData;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Text;
+#if !NETFRAMEWORK
+using static System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes;
+#endif
using static System.Globalization.CultureInfo;
using static System.Guid;
using static System.Reflection.BindingFlags;
@@ -22,6 +25,11 @@ namespace Asp.Versioning.OData;
///
/// Represents the default model type builder.
///
+#if !NETFRAMEWORK
+[UnconditionalSuppressMessage( "ILLink", "IL2055")]
+[UnconditionalSuppressMessage( "ILLink", "IL2070")]
+[UnconditionalSuppressMessage( "ILLink", "IL2073")]
+#endif
public sealed class DefaultModelTypeBuilder : IModelTypeBuilder
{
/* design: there is typically a 1:1 relationship between an edm and api version. odata model bound settings
@@ -59,7 +67,17 @@ private DefaultModelTypeBuilder( bool excludeAdHocModels, bool adHoc )
public DefaultModelTypeBuilder( bool includeAdHocModels = false ) => excludeAdHocModels = !includeAdHocModels;
///
- public Type NewStructuredType( IEdmModel model, IEdmStructuredType structuredType, Type clrType, ApiVersion apiVersion )
+#if !NETFRAMEWORK
+ [return: DynamicallyAccessedMembers( Interfaces | PublicProperties )]
+#endif
+ public Type NewStructuredType(
+ IEdmModel model,
+ IEdmStructuredType structuredType,
+#if !NETFRAMEWORK
+ [DynamicallyAccessedMembers( Interfaces | PublicProperties )]
+#endif
+ Type clrType,
+ ApiVersion apiVersion )
{
ArgumentNullException.ThrowIfNull( model );
@@ -88,6 +106,9 @@ public Type NewStructuredType( IEdmModel model, IEdmStructuredType structuredTyp
}
///
+#if !NETFRAMEWORK
+ [return: DynamicallyAccessedMembers( Interfaces | PublicProperties )]
+#endif
public Type NewActionParameters( IEdmModel model, IEdmAction action, string controllerName, ApiVersion apiVersion )
{
ArgumentNullException.ThrowIfNull( model );
@@ -417,10 +438,6 @@ private static PropertyBuilder AddProperty(
var field = addTo.DefineField( "_" + name, shouldBeAdded, FieldAttributes.Private );
var propertyBuilder = addTo.DefineProperty( name, PropertyAttributes.HasDefault, shouldBeAdded, null );
var getter = addTo.DefineMethod( "get_" + name, propertyMethodAttributes, shouldBeAdded, Type.EmptyTypes );
-
- /* returnType is 'null' instead of type(void) as per docs
- * see: https://learn.microsoft.com/en-us/dotnet/api/system.reflection.emit.propertybuilder?view=net-9.0
- */
var setter = addTo.DefineMethod( "set_" + name, propertyMethodAttributes, null, [shouldBeAdded] );
var il = getter.GetILGenerator();
diff --git a/src/Common/src/Common.OData.ApiExplorer/OData/IModelTypeBuilder.cs b/src/Common/src/Common.OData.ApiExplorer/OData/IModelTypeBuilder.cs
index 96b80e9f..cfc73a43 100644
--- a/src/Common/src/Common.OData.ApiExplorer/OData/IModelTypeBuilder.cs
+++ b/src/Common/src/Common.OData.ApiExplorer/OData/IModelTypeBuilder.cs
@@ -8,6 +8,9 @@ namespace Asp.Versioning.OData;
using Microsoft.AspNetCore.OData.Formatter;
#endif
using Microsoft.OData.Edm;
+#if !NETFRAMEWORK
+using static System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes;
+#endif
///
/// Defines the behavior of a model type builder.
@@ -26,7 +29,17 @@ public interface IModelTypeBuilder
/// structured type.
/// If a substitution is not required, the original CLR type is returned. When a substitution
/// type is generated, it is performed only once per API version.
- Type NewStructuredType( IEdmModel model, IEdmStructuredType structuredType, Type clrType, ApiVersion apiVersion );
+#if !NETFRAMEWORK
+ [return: DynamicallyAccessedMembers( Interfaces | PublicProperties )]
+#endif
+ Type NewStructuredType(
+ IEdmModel model,
+ IEdmStructuredType structuredType,
+#if !NETFRAMEWORK
+ [DynamicallyAccessedMembers( Interfaces | PublicProperties )]
+#endif
+ Type clrType,
+ ApiVersion apiVersion );
///
/// Creates an returns a strongly-typed definition for OData action parameters.
@@ -39,5 +52,8 @@ public interface IModelTypeBuilder
/// OData action parameters are modeled as a dictionary,
/// which is difficult to use effectively by documentation tools such as the API Explorer. The corresponding type is generated only once per
/// API version.
+#if !NETFRAMEWORK
+ [return: DynamicallyAccessedMembers( Interfaces | PublicProperties )]
+#endif
Type NewActionParameters( IEdmModel model, IEdmAction action, string controllerName, ApiVersion apiVersion );
}
\ No newline at end of file
diff --git a/src/Common/src/Common.OData.ApiExplorer/OData/TypeExtensions.cs b/src/Common/src/Common.OData.ApiExplorer/OData/TypeExtensions.cs
index a32cd16a..72c76457 100644
--- a/src/Common/src/Common.OData.ApiExplorer/OData/TypeExtensions.cs
+++ b/src/Common/src/Common.OData.ApiExplorer/OData/TypeExtensions.cs
@@ -16,6 +16,8 @@ namespace Asp.Versioning.OData;
using System.Runtime.CompilerServices;
#if NETFRAMEWORK
using IActionResult = System.Web.Http.IHttpActionResult;
+#else
+using static System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes;
#endif
///
@@ -41,7 +43,17 @@ public static partial class TypeExtensions
/// The current type substitution context.
/// The original or a substitution type based on the
/// provided .
- public static Type SubstituteIfNecessary( this Type type, TypeSubstitutionContext context )
+#if !NETFRAMEWORK
+ [UnconditionalSuppressMessage( "ILLink", "IL2026" )]
+ [UnconditionalSuppressMessage( "ILLink", "IL2073" )]
+ [return: DynamicallyAccessedMembers( Interfaces | PublicProperties )]
+#endif
+ public static Type SubstituteIfNecessary(
+#if !NETFRAMEWORK
+ [DynamicallyAccessedMembers( Interfaces | PublicProperties )]
+#endif
+ this Type type,
+ TypeSubstitutionContext context )
{
ArgumentNullException.ThrowIfNull( type );
ArgumentNullException.ThrowIfNull( context );
@@ -151,7 +163,13 @@ internal static Type ExtractInnerType( this Type type )
return type;
}
- private static bool IsSubstitutableGeneric( Type type, Stack openTypes, out Type? innerType )
+ private static bool IsSubstitutableGeneric(
+#if !NETFRAMEWORK
+ [DynamicallyAccessedMembers( Interfaces )]
+#endif
+ Type type,
+ Stack openTypes,
+ out Type? innerType )
{
innerType = default;
@@ -212,6 +230,10 @@ private static bool IsSubstitutableGeneric( Type type, Stack openTypes, ou
return true;
}
+#if !NETFRAMEWORK
+ [RequiresDynamicCode( "Might not be available at runtime" )]
+ [RequiresUnreferencedCode( "Cannot be validated by trim analysis" )]
+#endif
private static Type CloseGeneric( Stack openTypes, Type innerType )
{
var type = openTypes.Pop();
@@ -241,7 +263,10 @@ private static bool CanBeSubstituted( Type type ) =>
#endif
!type.IsODataActionParameters();
- internal static bool IsEnumerable( this Type type, [NotNullWhen( true )] out Type? itemType )
+#if !NETFRAMEWORK
+ [UnconditionalSuppressMessage( "ILLink", "IL2070" )]
+#endif
+ internal static bool IsEnumerable(this Type type, [NotNullWhen( true )] out Type? itemType )
{
var types = new Queue();
diff --git a/src/Common/test/Common.OData.ApiExplorer.Tests/OData/DefaultModelTypeBuilderTest.cs b/src/Common/test/Common.OData.ApiExplorer.Tests/OData/DefaultModelTypeBuilderTest.cs
index 2a0fc160..d5295031 100644
--- a/src/Common/test/Common.OData.ApiExplorer.Tests/OData/DefaultModelTypeBuilderTest.cs
+++ b/src/Common/test/Common.OData.ApiExplorer.Tests/OData/DefaultModelTypeBuilderTest.cs
@@ -410,16 +410,16 @@ public void substitute_should_resolve_types_that_reference_a_model_that_match_th
}
[Fact]
- public void substituted_type_should_have_valid_runtime_properties__issue1104()
+ public void ignoring_property_should_force_substitution_with_valid_runtime_properties()
{
// arrange
var modelBuilder = new ODataConventionModelBuilder();
-
var address = modelBuilder.EntitySet( nameof( Address ) ).EntityType;
- address.Ignore( x => x.City ); // force substitution
- var addressType = typeof( Address );
+
+ address.Ignore( x => x.City );
var context = NewContext( modelBuilder.GetEdmModel() );
+ var addressType = typeof( Address );
// act
var substitutedType = addressType.SubstituteIfNecessary( context );
@@ -428,6 +428,7 @@ public void substituted_type_should_have_valid_runtime_properties__issue1104()
substitutedType.Should().NotBe( addressType );
#if NET452
substitutedType.GetRuntimeProperties().Should().HaveCount( 5 );
+
foreach ( var substitutedProperty in substitutedType.GetRuntimeProperties() )
{
substitutedProperty.Should().NotBeNull();