Skip to content

Commit 6c18506

Browse files
authored
add package enhancements (#44)
* move http context to correct namespace * fix test namespaces * update code style * add roslyn and fix some hints
1 parent 2a344bc commit 6c18506

File tree

33 files changed

+950
-876
lines changed

33 files changed

+950
-876
lines changed

Directory.Packages.props

Lines changed: 54 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,55 @@
11
<Project>
2-
<PropertyGroup>
3-
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
4-
</PropertyGroup>
5-
<ItemGroup Label=".NET Dependencies">
6-
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="7.0.0" />
7-
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
8-
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
9-
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
10-
<PackageVersion Include="NaughtyStrings" Version="2.4.1" />
11-
</ItemGroup>
12-
<ItemGroup Label="ASP.NET Core Dependencies">
13-
<PackageVersion Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
14-
<PackageVersion Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
15-
</ItemGroup>
16-
<ItemGroup Label="Libraries for comparison">
17-
<PackageVersion Include="UAParser" Version="3.1.47" />
18-
<PackageVersion Include="DeviceDetector.NET" Version="4.3.0" />
19-
<PackageVersion Include="Ng.UserAgentService" Version="1.1.0" />
20-
</ItemGroup>
21-
<ItemGroup Label="Tests / Performance">
22-
<PackageVersion Include="BenchmarkDotNet" Version="0.13.11" />
23-
<PackageVersion Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.11" />
24-
<PackageVersion Include="NSubstitute" Version="5.1.0" />
25-
<PackageVersion Include="FluentAssertions" Version="7.0.0-alpha.2" />
26-
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0-preview-23503-02" />
27-
<PackageVersion Include="xunit" Version="2.6.3" />
28-
<PackageVersion Include="xunit.runner.console" Version="2.6.3">
29-
<PrivateAssets>all</PrivateAssets>
30-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
31-
</PackageVersion>
32-
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.5">
33-
<PrivateAssets>all</PrivateAssets>
34-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
35-
</PackageVersion>
36-
<PackageVersion Include="coverlet.msbuild" Version="6.0.0">
37-
<PrivateAssets>all</PrivateAssets>
38-
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
39-
</PackageVersion>
40-
</ItemGroup>
41-
</Project>
2+
<PropertyGroup>
3+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
4+
</PropertyGroup>
5+
6+
<ItemGroup Label=".NET Dependencies">
7+
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
8+
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
9+
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
10+
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" />
11+
<PackageVersion Include="NaughtyStrings" Version="2.4.1" />
12+
</ItemGroup>
13+
14+
<ItemGroup Label="Libraries for comparison">
15+
<PackageVersion Include="UAParser" Version="3.1.47" />
16+
<PackageVersion Include="DeviceDetector.NET" Version="6.3.3" />
17+
<PackageVersion Include="Ng.UserAgentService" Version="3.0.0" />
18+
</ItemGroup>
19+
20+
<ItemGroup Label="Tests / Performance">
21+
<PackageVersion Include="BenchmarkDotNet" Version="0.13.12" />
22+
<PackageVersion Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.12" />
23+
<PackageVersion Include="NSubstitute" Version="5.1.0" />
24+
<PackageVersion Include="FluentAssertions" Version="7.0.0-alpha.2" />
25+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
26+
<PackageVersion Include="xunit" Version="2.7.0" />
27+
<PackageVersion Include="xunit.runner.console" Version="2.7.0">
28+
<PrivateAssets>all</PrivateAssets>
29+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
30+
</PackageVersion>
31+
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.7">
32+
<PrivateAssets>all</PrivateAssets>
33+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
34+
</PackageVersion>
35+
<PackageVersion Include="coverlet.msbuild" Version="6.0.0">
36+
<PrivateAssets>all</PrivateAssets>
37+
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
38+
</PackageVersion>
39+
</ItemGroup>
40+
41+
<ItemGroup Label="Roslyn">
42+
<PackageVersion Include="Roslynator.Analyzers" Version="4.12.0">
43+
<PrivateAssets>all</PrivateAssets>
44+
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
45+
</PackageVersion>
46+
<PackageVersion Include="Roslynator.Formatting.Analyzers" Version="4.12.0">
47+
<PrivateAssets>all</PrivateAssets>
48+
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
49+
</PackageVersion>
50+
<PackageVersion Include="Roslynator.CodeAnalysis.Analyzers" Version="4.12.0">
51+
<PrivateAssets>all</PrivateAssets>
52+
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
53+
</PackageVersion>
54+
</ItemGroup>
55+
</Project>

src/MyCSharp.HttpUserAgentParser.AspNetCore/DependencyInjection/HttpUserAgentParserDependencyInjectionOptionsExtensions.cs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,21 @@
44
using MyCSharp.HttpUserAgentParser.DependencyInjection;
55
using MyCSharp.HttpUserAgentParser.Providers;
66

7-
namespace MyCSharp.HttpUserAgentParser.AspNetCore.DependencyInjection
7+
namespace MyCSharp.HttpUserAgentParser.AspNetCore.DependencyInjection;
8+
9+
/// <summary>
10+
/// Dependency injection extensions for ASP.NET Core environments
11+
/// </summary>
12+
public static class HttpUserAgentParserDependencyInjectionOptionsExtensions
813
{
914
/// <summary>
10-
/// Dependency injection extensions for ASP.NET Core environments
15+
/// Registers <see cref="HttpUserAgentParserAccessor"/> as <see cref="IHttpUserAgentParserAccessor"/>.
16+
/// Requires a registered <see cref="IHttpUserAgentParserProvider"/>
1117
/// </summary>
12-
public static class HttpUserAgentParserDependencyInjectionOptionsExtensions
18+
public static HttpUserAgentParserDependencyInjectionOptions AddHttpUserAgentParserAccessor(
19+
this HttpUserAgentParserDependencyInjectionOptions options)
1320
{
14-
/// <summary>
15-
/// Registers <see cref="HttpUserAgentParserAccessor"/> as <see cref="IHttpUserAgentParserAccessor"/>.
16-
/// Requires a registered <see cref="IHttpUserAgentParserProvider"/>
17-
/// </summary>
18-
public static HttpUserAgentParserDependencyInjectionOptions AddHttpUserAgentParserAccessor(
19-
this HttpUserAgentParserDependencyInjectionOptions options)
20-
{
21-
options.Services.AddSingleton<IHttpUserAgentParserAccessor, HttpUserAgentParserAccessor>();
22-
return options;
23-
}
21+
options.Services.AddSingleton<IHttpUserAgentParserAccessor, HttpUserAgentParserAccessor>();
22+
return options;
2423
}
2524
}

src/MyCSharp.HttpUserAgentParser/HttpContextExtensions.cs renamed to src/MyCSharp.HttpUserAgentParser.AspNetCore/HttpContextExtensions.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
using Microsoft.AspNetCore.Http;
44
using Microsoft.Extensions.Primitives;
55

6-
namespace MyCSharp.HttpUserAgentParser;
6+
namespace MyCSharp.HttpUserAgentParser.AspNetCore;
77

88
/// <summary>
99
/// Static extensions for <see cref="HttpContext"/>
@@ -16,9 +16,7 @@ public static class HttpContextExtensions
1616
public static string? GetUserAgentString(this HttpContext httpContext)
1717
{
1818
if (httpContext.Request.Headers.TryGetValue("User-Agent", out StringValues value))
19-
{
2019
return value;
21-
}
2220

2321
return null;
2422
}

src/MyCSharp.HttpUserAgentParser.AspNetCore/HttpUserAgentParserAccessor.cs

Lines changed: 21 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,57 +3,36 @@
33
using Microsoft.AspNetCore.Http;
44
using MyCSharp.HttpUserAgentParser.Providers;
55

6-
namespace MyCSharp.HttpUserAgentParser.AspNetCore
6+
namespace MyCSharp.HttpUserAgentParser.AspNetCore;
7+
8+
/// <summary>
9+
/// User Agent parser accessor. Implements <see cref="IHttpContextAccessor.HttpContext"/>
10+
/// </summary>
11+
/// <remarks>
12+
/// Creates a new instance of <see cref="HttpUserAgentParserAccessor"/>
13+
/// </remarks>
14+
public class HttpUserAgentParserAccessor(IHttpUserAgentParserProvider httpUserAgentParser)
15+
: IHttpUserAgentParserAccessor
716
{
17+
private readonly IHttpUserAgentParserProvider _httpUserAgentParser = httpUserAgentParser;
18+
819
/// <summary>
9-
/// User Agent parser accessor
20+
/// User agent of current <see cref="IHttpContextAccessor"/>
1021
/// </summary>
11-
public interface IHttpUserAgentParserAccessor
12-
{
13-
/// <summary>
14-
/// User agent value
15-
/// </summary>
16-
string? GetHttpContextUserAgent(HttpContext httpContext);
17-
18-
/// <summary>
19-
/// Returns current <see cref="HttpUserAgentInformation"/>
20-
/// </summary>
21-
HttpUserAgentInformation? Get(HttpContext httpContext);
22-
}
22+
public string? GetHttpContextUserAgent(HttpContext httpContext)
23+
=> httpContext.GetUserAgentString();
2324

2425
/// <summary>
25-
/// User Agent parser accessor. Implements <see cref="IHttpContextAccessor.HttpContext"/>
26+
/// Returns current <see cref="HttpUserAgentInformation"/> of current <see cref="IHttpContextAccessor"/>
2627
/// </summary>
27-
public class HttpUserAgentParserAccessor : IHttpUserAgentParserAccessor
28+
public HttpUserAgentInformation? Get(HttpContext httpContext)
2829
{
29-
private readonly IHttpUserAgentParserProvider _httpUserAgentParser;
30-
31-
/// <summary>
32-
/// Creates a new instance of <see cref="HttpUserAgentParserAccessor"/>
33-
/// </summary>
34-
public HttpUserAgentParserAccessor(IHttpUserAgentParserProvider httpUserAgentParser)
30+
string? httpUserAgent = GetHttpContextUserAgent(httpContext);
31+
if (string.IsNullOrEmpty(httpUserAgent))
3532
{
36-
_httpUserAgentParser = httpUserAgentParser;
33+
return null;
3734
}
3835

39-
/// <summary>
40-
/// User agent of current <see cref="IHttpContextAccessor"/>
41-
/// </summary>
42-
public string? GetHttpContextUserAgent(HttpContext httpContext)
43-
=> httpContext.GetUserAgentString();
44-
45-
/// <summary>
46-
/// Returns current <see cref="HttpUserAgentInformation"/> of current <see cref="IHttpContextAccessor"/>
47-
/// </summary>
48-
public HttpUserAgentInformation? Get(HttpContext httpContext)
49-
{
50-
string? httpUserAgent = GetHttpContextUserAgent(httpContext);
51-
if (string.IsNullOrEmpty(httpUserAgent))
52-
{
53-
return null;
54-
}
55-
56-
return _httpUserAgentParser.Parse(httpUserAgent);
57-
}
36+
return _httpUserAgentParser.Parse(httpUserAgent);
5837
}
5938
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright © myCSharp.de - all rights reserved
2+
3+
using Microsoft.AspNetCore.Http;
4+
5+
namespace MyCSharp.HttpUserAgentParser.AspNetCore;
6+
7+
/// <summary>
8+
/// User Agent parser accessor
9+
/// </summary>
10+
public interface IHttpUserAgentParserAccessor
11+
{
12+
/// <summary>
13+
/// User agent value
14+
/// </summary>
15+
string? GetHttpContextUserAgent(HttpContext httpContext);
16+
17+
/// <summary>
18+
/// Returns current <see cref="HttpUserAgentInformation"/>
19+
/// </summary>
20+
HttpUserAgentInformation? Get(HttpContext httpContext);
21+
}

src/MyCSharp.HttpUserAgentParser.AspNetCore/MyCSharp.HttpUserAgentParser.AspNetCore.csproj

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,26 @@
1616
<None Include="readme.md" Pack="true" PackagePath="" />
1717
<None Include="LICENSE.txt" Pack="true" PackagePath="" />
1818
</ItemGroup>
19-
19+
2020
<ItemGroup>
2121
<FrameworkReference Include="Microsoft.AspNetCore.App" />
2222
</ItemGroup>
2323

24+
<ItemGroup Label="NuGet Roslyn">
25+
<PackageReference Include="Roslynator.Analyzers">
26+
<PrivateAssets>all</PrivateAssets>
27+
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
28+
</PackageReference>
29+
<PackageReference Include="Roslynator.CodeAnalysis.Analyzers">
30+
<PrivateAssets>all</PrivateAssets>
31+
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
32+
</PackageReference>
33+
<PackageReference Include="Roslynator.Formatting.Analyzers">
34+
<PrivateAssets>all</PrivateAssets>
35+
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
36+
</PackageReference>
37+
</ItemGroup>
38+
2439
<ItemGroup>
2540
<ProjectReference Include="..\MyCSharp.HttpUserAgentParser\MyCSharp.HttpUserAgentParser.csproj" />
2641
</ItemGroup>
Lines changed: 37 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,58 @@
11
// Copyright © myCSharp.de - all rights reserved
22

3-
using System;
43
using Microsoft.Extensions.Caching.Memory;
54
using MyCSharp.HttpUserAgentParser.Providers;
65

7-
namespace MyCSharp.HttpUserAgentParser.MemoryCache
6+
namespace MyCSharp.HttpUserAgentParser.MemoryCache;
7+
8+
/// <inheritdoc/>
9+
/// <summary>
10+
/// Creates a new instance of <see cref="HttpUserAgentParserMemoryCachedProvider"/>.
11+
/// </summary>
12+
/// <param name="options">The options used to set expiration and size limit</param>
13+
public class HttpUserAgentParserMemoryCachedProvider(
14+
HttpUserAgentParserMemoryCachedProviderOptions options) : IHttpUserAgentParserProvider
815
{
16+
private readonly Microsoft.Extensions.Caching.Memory.MemoryCache _memoryCache = new(options.CacheOptions);
17+
private readonly HttpUserAgentParserMemoryCachedProviderOptions _options = options;
18+
919
/// <inheritdoc/>
10-
public class HttpUserAgentParserMemoryCachedProvider : IHttpUserAgentParserProvider
20+
public HttpUserAgentInformation Parse(string userAgent)
1121
{
12-
private readonly Microsoft.Extensions.Caching.Memory.MemoryCache _memoryCache;
13-
private readonly HttpUserAgentParserMemoryCachedProviderOptions _options;
14-
15-
/// <summary>
16-
/// Creates a new instance of <see cref="HttpUserAgentParserMemoryCachedProvider"/>.
17-
/// </summary>
18-
/// <param name="options">The options used to set expiration and size limit</param>
19-
public HttpUserAgentParserMemoryCachedProvider(HttpUserAgentParserMemoryCachedProviderOptions options)
20-
{
21-
_memoryCache = new Microsoft.Extensions.Caching.Memory.MemoryCache(options.CacheOptions);
22-
_options = options;
23-
}
22+
CacheKey key = this.GetKey(userAgent);
2423

25-
/// <inheritdoc/>
26-
public HttpUserAgentInformation Parse(string userAgent)
24+
return _memoryCache.GetOrCreate(key, static entry =>
2725
{
28-
CacheKey key = this.GetKey(userAgent);
29-
30-
return _memoryCache.GetOrCreate(key, static entry =>
31-
{
32-
CacheKey key = (entry.Key as CacheKey)!;
33-
entry.SlidingExpiration = key.Options.CacheEntryOptions.SlidingExpiration;
34-
entry.SetSize(1);
26+
CacheKey key = (entry.Key as CacheKey)!;
27+
entry.SlidingExpiration = key.Options.CacheEntryOptions.SlidingExpiration;
28+
entry.SetSize(1);
3529

36-
return HttpUserAgentParser.Parse(key.UserAgent);
37-
});
38-
}
30+
return HttpUserAgentParser.Parse(key.UserAgent);
31+
});
32+
}
3933

40-
[ThreadStatic]
41-
private static CacheKey? s_tKey;
34+
[ThreadStatic]
35+
private static CacheKey? s_tKey;
4236

43-
private CacheKey GetKey(string userAgent)
44-
{
45-
CacheKey key = s_tKey ??= new CacheKey();
37+
private CacheKey GetKey(string userAgent)
38+
{
39+
CacheKey key = s_tKey ??= new CacheKey();
4640

47-
key.UserAgent = userAgent;
48-
key.Options = _options;
41+
key.UserAgent = userAgent;
42+
key.Options = _options;
4943

50-
return key;
51-
}
44+
return key;
45+
}
5246

53-
private class CacheKey : IEquatable<CacheKey> // required for IMemoryCache
54-
{
55-
public string UserAgent { get; set; } = null!;
47+
private class CacheKey : IEquatable<CacheKey> // required for IMemoryCache
48+
{
49+
public string UserAgent { get; set; } = null!;
5650

57-
public HttpUserAgentParserMemoryCachedProviderOptions Options { get; set; } = null!;
51+
public HttpUserAgentParserMemoryCachedProviderOptions Options { get; set; } = null!;
5852

59-
public bool Equals(CacheKey? other) => this.UserAgent == other?.UserAgent;
60-
public override bool Equals(object? obj) => this.Equals(obj as CacheKey);
53+
public bool Equals(CacheKey? other) => this.UserAgent == other?.UserAgent;
54+
public override bool Equals(object? obj) => this.Equals(obj as CacheKey);
6155

62-
public override int GetHashCode() => this.UserAgent.GetHashCode();
63-
}
56+
public override int GetHashCode() => this.UserAgent.GetHashCode();
6457
}
6558
}

0 commit comments

Comments
 (0)