Skip to content

Commit 4469d27

Browse files
committed
Add netstandard2.0 and net462 support, add Blazor WASM sample and enable AOT analyzer
- Added netstandard2.0 and net462 targets to the core Refit.Composite project. - Conditionalized modern C# 11+ generic attributes and string validations for backward compatibility. - Implemented IsAotCompatible analyzer with conditional TargetFramework checks. - Created an official Blazor WASM integration sample inside the 'tests/' directory. - Separated testing and sample packages via nested Central Package Management (CPM).
1 parent bc34cf9 commit 4469d27

23 files changed

Lines changed: 345 additions & 30 deletions

Directory.Packages.props

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@
77
<PackageVersion Include="Refit.HttpClientFactory" Version="[11.0.0, 12.0.0)" />
88
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="5.3.0"/>
99
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="5.3.0"/>
10-
<PackageVersion Include="coverlet.collector" Version="6.0.4"/>
11-
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1"/>
12-
<PackageVersion Include="xunit" Version="2.9.3"/>
13-
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.4"/>
14-
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0"/>
1510
</ItemGroup>
1611

1712
</Project>

Refit.Composite.slnx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
</Folder>
1010
<Folder Name="/tests/">
1111
<Project Path="tests/Refit.Composite.Benchmarks/Refit.Composite.Benchmarks.csproj" />
12+
<Project Path="tests/Refit.Composite.Sample.Wasm/Refit.Composite.Sample.Wasm.csproj" />
1213
<Project Path="tests/Refit.Composite.Sample/Refit.Composite.Sample.csproj" />
1314
<Project Path="tests/Refit.Composite.Tests/Refit.Composite.Tests.csproj" />
1415
</Folder>

src/Refit.Composite.SourceGenerator/CompositeApiGenerator.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,14 @@ private static string GenerateExtensionClass(INamedTypeSymbol interfaceSymbol)
9797
sb.AppendLine();
9898
}
9999

100+
sb.AppendLine("#if NET5_0_OR_GREATER || NETCOREAPP3_0_OR_GREATER");
100101
sb.AppendLine(" [global::System.Diagnostics.CodeAnalysis.DynamicDependency(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All, typeof(global::System.Object))]");
102+
sb.AppendLine("#endif");
101103
sb.AppendLine($" public {className}(global::System.IServiceProvider serviceProvider)");
102104
sb.AppendLine(" {");
103105
sb.AppendLine(" _serviceProvider = serviceProvider;");
104106
sb.AppendLine(" }");
107+
105108
sb.AppendLine("}");
106109

107110
return sb.ToString();

src/Refit.Composite/Attributes/ApiHandlerAttribute.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace Refit.Composite.Attributes;
1+
using System.Net.Http;
2+
3+
namespace Refit.Composite.Attributes;
24

35
/// <summary>
46
/// Registers a custom <see cref="DelegatingHandler"/> to be executed in the HttpClient pipeline.
@@ -33,7 +35,7 @@ public ApiHandlerAttribute(Type handler)
3335
/// </summary>
3436
/// <typeparam name="THandler">The type of the handler that inherits from <see cref="DelegatingHandler"/>.</typeparam>
3537
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Property, AllowMultiple = true)]
36-
public class ApiHandlerAttribute<THandler> : ApiHandlerAttribute
38+
public class ApiHandlerAttribute<THandler> : ApiHandlerAttribute
3739
where THandler : DelegatingHandler
3840
{
3941
/// <summary>
@@ -42,4 +44,4 @@ public class ApiHandlerAttribute<THandler> : ApiHandlerAttribute
4244
public ApiHandlerAttribute() : base(typeof(THandler))
4345
{
4446
}
45-
}
47+
}

src/Refit.Composite/Attributes/ApiIgnoreHandlerAttribute.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
namespace Refit.Composite.Attributes;
1+
using System.Net.Http;
2+
3+
namespace Refit.Composite.Attributes;
24

35
/// <summary>
4-
/// Excludes a specific <see cref="DelegatingHandler"/> from the current HttpClient pipeline
6+
/// Excludes a specific <see cref="DelegatingHandler"/> from the current HttpClient pipeline
57
/// if it was previously added by global configuration or prior attributes.
68
/// </summary>
79
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
@@ -23,12 +25,12 @@ public ApiIgnoreHandlerAttribute(Type handler)
2325
}
2426

2527
/// <summary>
26-
/// Excludes a specific <see cref="DelegatingHandler"/> from the current HttpClient pipeline
28+
/// Excludes a specific <see cref="DelegatingHandler"/> from the current HttpClient pipeline
2729
/// if it was previously added by global configuration or prior attributes.
2830
/// </summary>
2931
/// <typeparam name="THandler">The type of the handler to exclude.</typeparam>
3032
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
31-
public class ApiIgnoreHandlerAttribute<THandler> : ApiIgnoreHandlerAttribute
33+
public class ApiIgnoreHandlerAttribute<THandler> : ApiIgnoreHandlerAttribute
3234
where THandler : DelegatingHandler
3335
{
3436
/// <summary>
@@ -37,4 +39,4 @@ public class ApiIgnoreHandlerAttribute<THandler> : ApiIgnoreHandlerAttribute
3739
public ApiIgnoreHandlerAttribute() : base(typeof(THandler))
3840
{
3941
}
40-
}
42+
}

src/Refit.Composite/Handlers/ErrorHandlingHandler.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Net;
2+
using System.Net.Http;
23

34
namespace Refit.Composite.Handlers;
45

@@ -24,4 +25,4 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
2425
};
2526
}
2627
}
27-
}
28+
}

src/Refit.Composite/Handlers/ShortLoggingHandler.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Diagnostics;
22
using System.Net;
3+
using System.Net.Http;
34
using Microsoft.Extensions.Logging;
45

56
namespace Refit.Composite.Handlers;
@@ -12,9 +13,9 @@ public class ShortLoggingHandler(ILogger<ShortLoggingHandler> logger) : Delegati
1213
{
1314
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken ct)
1415
{
15-
var startTime = Stopwatch.GetTimestamp();
16+
var sw = Stopwatch.StartNew();
1617
var response = await base.SendAsync(request, ct);
17-
var elapsedMs = Stopwatch.GetElapsedTime(startTime).TotalMilliseconds;
18+
sw.Stop();
1819

1920
var level = response.StatusCode switch
2021
{
@@ -24,7 +25,7 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
2425
};
2526

2627
logger.Log(level, "HTTP {Method} {Uri} responded {StatusCode} in {Elapsed:F2} ms",
27-
request.Method, request.RequestUri, (int)response.StatusCode, elapsedMs);
28+
request.Method, request.RequestUri, (int)response.StatusCode, sw.Elapsed.TotalMilliseconds);
2829

2930
return response;
3031
}

src/Refit.Composite/Refit.Composite.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>net10.0;net9.0;net8.0;</TargetFrameworks>
4+
<TargetFrameworks>net10.0;net9.0;net8.0;netstandard2.0;net462</TargetFrameworks>
55

66
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
77
<PackageId>HappyEntity.Refit.Composite</PackageId>
88
<Title>HappyEntity.Refit.Composite</Title>
99

1010
<IsAotCompatible>true</IsAotCompatible>
1111
<PublishAotSupported>true</PublishAotSupported>
12+
<IsAotCompatible Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0'))">true</IsAotCompatible>
1213
</PropertyGroup>
1314

1415
<ItemGroup>

src/Refit.Composite/RefitCompositeExtensions.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Diagnostics.CodeAnalysis;
2+
using System.Net.Http;
23
using System.Reflection;
34
using Microsoft.Extensions.DependencyInjection.Extensions;
45
using Refit;
@@ -27,15 +28,27 @@ public static class RefitCompositeExtensions
2728
/// <exception cref="ArgumentException">Thrown when <paramref name="baseApi"/> is null or empty.</exception>
2829
/// <exception cref="UriFormatException">Thrown when <paramref name="baseApi"/> is not a valid URI.</exception>
2930
/// <exception cref="InvalidDataException">Thrown when the composite interface contains duplicate API definitions or invalid handler registrations.</exception>
31+
#if NET5_0_OR_GREATER || NETCOREAPP3_0_OR_GREATER
3032
[RequiresUnreferencedCode("Scans composite API interface properties via reflection to configure HttpClient pipelines.")]
33+
#endif
3134
public static IServiceCollection AddRefitComposite<
35+
#if NET5_0_OR_GREATER || NETCOREAPP3_0_OR_GREATER
3236
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
37+
#endif
3338
TApi>(
3439
this IServiceCollection services,
3540
string baseApi, RefitSettings? settings = null, Action<IHttpClientBuilder>? configure = null)
3641
where TApi : class, IRefitComposite
3742
{
43+
#if NET7_0_OR_GREATER
3844
ArgumentException.ThrowIfNullOrEmpty(baseApi);
45+
#else
46+
if (string.IsNullOrEmpty(baseApi))
47+
{
48+
throw new ArgumentException("The base API URL cannot be null or empty.", nameof(baseApi));
49+
}
50+
#endif
51+
3952
return services.AddRefitComposite<TApi>(new Uri(baseApi), settings, configure);
4053
}
4154

@@ -51,9 +64,14 @@ public static IServiceCollection AddRefitComposite<
5164
/// <param name="configure">An optional delegate to further configure the underlying <see cref="IHttpClientBuilder"/> for each registered API client.</param>
5265
/// <returns>The same <see cref="IServiceCollection"/> instance for chaining.</returns>
5366
/// <exception cref="InvalidDataException">Thrown when the composite interface contains duplicate API definitions or invalid handler registrations.</exception>
67+
#if NET5_0_OR_GREATER || NETCOREAPP3_0_OR_GREATER
5468
[RequiresUnreferencedCode("Scans composite API interface properties via reflection to configure HttpClient pipelines.")]
69+
#endif
5570
public static IServiceCollection AddRefitComposite<
56-
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] TApi>(
71+
#if NET5_0_OR_GREATER || NETCOREAPP3_0_OR_GREATER
72+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
73+
#endif
74+
TApi>(
5775
this IServiceCollection services,
5876
Uri baseApi, RefitSettings? settings = null, Action<IHttpClientBuilder>? configure = null)
5977
where TApi : class, IRefitComposite

tests/Directory.Packages.props

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<Project>
2+
<PropertyGroup>
3+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
4+
</PropertyGroup>
5+
6+
<ItemGroup>
7+
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0"/>
8+
9+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1"/>
10+
<PackageVersion Include="coverlet.collector" Version="6.0.4"/>
11+
12+
<PackageVersion Include="xunit" Version="2.9.3"/>
13+
<PackageVersion Include="xunit.v3" Version="3.2.2"/>
14+
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.4"/>
15+
16+
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.9"/>
17+
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.9"/>
18+
<PackageVersion Include="HappyEntity.Refit.Composite" Version="2.0.3"/>
19+
</ItemGroup>
20+
21+
</Project>

0 commit comments

Comments
 (0)