Skip to content

Commit a6b8d78

Browse files
authored
.NET 9 (#11)
deprecate .NET 7 add .NET 9 +semver:major
1 parent 6e5f44a commit a6b8d78

File tree

9 files changed

+95
-97
lines changed

9 files changed

+95
-97
lines changed

.editorconfig

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ root = true
33

44
[*]
55
charset = utf-8
6+
insert_final_newline = true
67

78
# C# files
89
[*.cs]
@@ -15,8 +16,9 @@ indent_style = space
1516
tab_width = 4
1617

1718
# New line preferences
18-
end_of_line = lf
19-
insert_final_newline = false
19+
insert_final_newline = true
20+
trim_trailing_whitespace = true
21+
2022

2123
#### .NET Coding Conventions ####
2224

@@ -37,7 +39,7 @@ dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
3739
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
3840

3941
# Modifier preferences
40-
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
42+
dotnet_style_require_accessibility_modifiers = for_non_interface_members:warning
4143

4244
# Expression-level preferences
4345
csharp_style_deconstructed_variable_declaration = true:suggestion
@@ -65,9 +67,9 @@ dotnet_code_quality_unused_parameters = all:suggestion
6567
#### C# Coding Conventions ####
6668

6769
# var preferences
68-
csharp_style_var_elsewhere = false:silent
69-
csharp_style_var_for_built_in_types = false:silent
70-
csharp_style_var_when_type_is_apparent = false:silent
70+
csharp_style_var_elsewhere = true:silent
71+
csharp_style_var_for_built_in_types = true:silent
72+
csharp_style_var_when_type_is_apparent = true:silent
7173

7274
# Expression-bodied members
7375
csharp_style_expression_bodied_accessors = true:silent
@@ -87,7 +89,7 @@ csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
8789
csharp_style_conditional_delegate_call = true:suggestion
8890

8991
# Modifier preferences
90-
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
92+
csharp_preferred_modifier_order = public, private, protected, internal, static, extern, new, virtual, abstract, sealed, override, readonly, unsafe, volatile, async
9193

9294
# Code-block preferences
9395
csharp_prefer_braces = true:silent
@@ -100,6 +102,12 @@ csharp_style_prefer_range_operator = true:suggestion
100102
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
101103
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
102104

105+
# C# 10
106+
csharp_style_namespace_declarations = file_scoped:error
107+
csharp_style_prefer_primary_constructors = true
108+
dotnet_diagnostic.IDE0290.severity = error
109+
110+
103111
#### C# Formatting Rules ####
104112

105113
# New line preferences
@@ -146,3 +154,9 @@ csharp_space_between_square_brackets = false
146154
# Wrapping preferences
147155
csharp_preserve_single_line_blocks = true
148156
csharp_preserve_single_line_statements = true
157+
158+
159+
[*.csproj]
160+
indent_size = 2
161+
indent_style = space
162+
tab_width = 2

.github/workflows/CI.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ jobs:
1515
matrix:
1616
os: [ubuntu-latest, windows-latest]
1717
steps:
18-
- uses: actions/checkout@v3
19-
- uses: actions/setup-dotnet@v3
18+
- uses: actions/checkout@v4
19+
- uses: actions/setup-dotnet@v4
2020
with:
21-
dotnet-version: 8.0.x
21+
dotnet-version: 9.0.x
2222
- run: dotnet --info
2323
- name: Restore dependencies
2424
run: dotnet restore

.github/workflows/PreRelease.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ jobs:
88
runs-on: ubuntu-latest
99

1010
steps:
11-
- uses: actions/checkout@v3
11+
- uses: actions/checkout@v4
1212
with:
1313
fetch-depth: 0
14-
- uses: actions/setup-dotnet@v3
14+
- uses: actions/setup-dotnet@v4
1515
with:
16-
dotnet-version: 8.0.x
16+
dotnet-version: 9.0.x
1717
- name: Restore dependencies
1818
run: dotnet restore
1919
- name: Build

.github/workflows/Release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ jobs:
1111
- uses: actions/checkout@v3
1212
with:
1313
fetch-depth: 0
14-
- uses: actions/setup-dotnet@v3
14+
- uses: actions/setup-dotnet@v4
1515
with:
16-
dotnet-version: 8.0.x
16+
dotnet-version: 9.0.x
1717
- name: Restore dependencies
1818
run: dotnet restore
1919
- name: Build

src/CronBackgroundServices/CronBackgroundService.cs

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,16 @@
33

44
namespace CronBackgroundServices;
55

6-
internal class CronBackgroundService : BackgroundService
6+
internal class CronBackgroundService(IRecurringAction Action, ILogger logger) : BackgroundService
77
{
8-
protected readonly IRecurringAction Action;
9-
private readonly ILogger _logger;
10-
private readonly Timing _timing;
8+
private readonly Timing _timing = new(Action.GetTimeZoneId());
119

12-
public CronBackgroundService(IRecurringAction action, ILogger logger)
13-
{
14-
_timing = new Timing(action.GetTimeZoneId());
15-
Action = action;
16-
_logger = logger;
17-
Cron = action.Cron;
18-
_logger.LogTrace($"Using {Cron} and timezone '{_timing.TimeZoneInfo.Id}. The time in this timezone: {_timing.RelativeNow()}'");
19-
}
20-
21-
private string Cron { get; }
10+
private string Cron { get; } = Action.Cron;
2211

2312
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
2413
{
14+
logger.LogTrace(
15+
$"Using {Cron} and timezone '{_timing.TimeZoneInfo.Id}. The time in this timezone: {_timing.RelativeNow()}'");
2516
DateTimeOffset? next = null;
2617

2718
do
@@ -33,7 +24,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
3324
next = _timing.GetNextOccurenceInRelativeTime(Cron);
3425
var uText = _timing.Get10NextOccurrences(Cron);
3526
var logText = $"Ten next occurrences :\n{uText.Aggregate((x, y) => x + "\n" + y)}";
36-
_logger.LogTrace(logText);
27+
logger.LogTrace(logText);
3728
}
3829

3930
if (now > next)
@@ -44,11 +35,13 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
4435
}
4536
catch (Exception e)
4637
{
47-
_logger.LogError(e, e.Message);
38+
logger.LogError(e, e.Message);
4839
}
4940

5041
next = _timing.GetNextOccurenceInRelativeTime(Cron);
51-
_logger.LogTrace($"Next at {next.Value.DateTime.ToLongDateString()} {next.Value.DateTime.ToLongTimeString()}");
42+
logger.LogTrace(next is not null
43+
? $"Next at {next.Value.DateTime.ToLongDateString()} {next.Value.DateTime.ToLongTimeString()}"
44+
: "No more occurences.");
5245
}
5346
else
5447
{
@@ -57,7 +50,6 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
5750
// cron occurence (lowest possible: every second)
5851
await Task.Delay(100);
5952
}
60-
6153
} while (!stoppingToken.IsCancellationRequested);
6254
}
6355
}
Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,33 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

3-
<PropertyGroup>
4-
<TargetFrameworks>net8.0;net7.0</TargetFrameworks>
5-
<RootNamespace>CronBackgroundServices</RootNamespace>
6-
<PackageId>CronBackgroundServices</PackageId>
7-
<Authors>John Korsnes</Authors>
8-
<Description>
9-
A .NET Core Background Service using Cron expressions as triggers
10-
</Description>
11-
<PackageTags>dotnetcore</PackageTags>
12-
<PackageProjectUrl>https://github.com/slackbot-net/slackbot.net</PackageProjectUrl>
13-
<License>https://github.com/slackbot-net/slackbot.net/blob/master/LICENSE</License>
14-
<RepositoryUrl>https://github.com/slackbot-net/slackbot.net</RepositoryUrl>
15-
<PackageIconUrl>images/cron.png</PackageIconUrl>
16-
<PackageIcon>cron.png</PackageIcon>
17-
<RepositoryType>git</RepositoryType>
18-
<ImplicitUsings>enable</ImplicitUsings>
19-
<LangVersion>latest</LangVersion>
20-
</PropertyGroup>
21-
22-
<ItemGroup>
23-
<PackageReference Include="Cronos" Version="0.7.1" />
24-
</ItemGroup>
25-
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
26-
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0" />
27-
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
28-
</ItemGroup>
29-
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
30-
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0" />
31-
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
32-
</ItemGroup>
33-
34-
<ItemGroup>
35-
<None Include="images/cron.png" Pack="true" PackagePath="" />
36-
</ItemGroup>
3+
<PropertyGroup>
4+
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
5+
<RootNamespace>CronBackgroundServices</RootNamespace>
6+
<PackageId>CronBackgroundServices</PackageId>
7+
<Authors>John Korsnes</Authors>
8+
<Description>
9+
A .NET Core Background Service using Cron expressions as triggers
10+
</Description>
11+
<PackageTags>dotnetcore</PackageTags>
12+
<PackageProjectUrl>https://github.com/slackbot-net/slackbot.net</PackageProjectUrl>
13+
<License>https://github.com/slackbot-net/slackbot.net/blob/master/LICENSE</License>
14+
<RepositoryUrl>https://github.com/slackbot-net/slackbot.net</RepositoryUrl>
15+
<PackageIconUrl>images/cron.png</PackageIconUrl>
16+
<PackageIcon>cron.png</PackageIcon>
17+
<RepositoryType>git</RepositoryType>
18+
<ImplicitUsings>enable</ImplicitUsings>
19+
<Nullable>enable</Nullable>
20+
<LangVersion>latest</LangVersion>
21+
</PropertyGroup>
3722

23+
<ItemGroup>
24+
<PackageReference Include="Cronos" Version="0.7.1"/>
25+
</ItemGroup>
26+
<ItemGroup>
27+
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.0"/>
28+
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0"/>
29+
</ItemGroup>
30+
<ItemGroup>
31+
<None Include="images/cron.png" Pack="true" PackagePath=""/>
32+
</ItemGroup>
3833
</Project>

src/CronBackgroundServices/Hosting/ServiceCollectionExtensions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
namespace CronBackgroundServices;
66

7-
public static class SlackbotWorkerBuilderExtensions
7+
public static class ServiceCollectionExtensions
88
{
99
/// <summary>
10-
/// For distributed apps
10+
/// For distributed apps
1111
/// </summary>
1212
public static IServiceCollection AddRecurrer<T>(this IServiceCollection services) where T : class, IRecurringAction
1313
{
@@ -16,7 +16,7 @@ public static IServiceCollection AddRecurrer<T>(this IServiceCollection services
1616
{
1717
var allRecurrers = s.GetServices<IRecurringAction>();
1818
var single = allRecurrers.First(r => r is T);
19-
var loggerFactory = s.GetService<ILoggerFactory>();
19+
var loggerFactory = s.GetRequiredService<ILoggerFactory>();
2020
var logger = loggerFactory.CreateLogger<T>();
2121
return new CronBackgroundService(single, logger);
2222
});

src/CronBackgroundServices/IRecurringAction.cs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,28 @@ namespace CronBackgroundServices;
55
public interface IRecurringAction
66
{
77
/// <summary>
8-
/// The job to be executed at intervals defined by the Cron expression
8+
/// The cron expression (including seconds) as defined by the Cronos library:
9+
/// See https://github.com/HangfireIO/Cronos#cron-format
10+
/// Ex: Every second: */1 * * * * *
11+
/// Ex: Every minute: 0 */1 * * * *
12+
/// Ex: Every midnight: 0 0 */1 * * *
13+
/// Ex: First of every month 0 0 0 1 * *
914
/// </summary>
10-
/// <returns></returns>
11-
Task Process(CancellationToken stoppingToken);
15+
/// <returns>A valid Cron Expression</returns>
16+
string Cron { get; }
1217

1318
/// <summary>
14-
/// The cron expression (including seconds) as defined by the Cronos library:
15-
/// See https://github.com/HangfireIO/Cronos#cron-format
16-
/// Ex: Every second: */1 * * * * *
17-
/// Ex: Every minute: 0 */1 * * * *
18-
/// Ex: Every midnight: 0 0 */1 * * *
19-
/// Ex: First of every month 0 0 0 1 * *
19+
/// The job to be executed at intervals defined by the Cron expression
2020
/// </summary>
21-
/// <returns>A valid Cron Expression</returns>
22-
string Cron { get; }
21+
/// <returns></returns>
22+
Task Process(CancellationToken stoppingToken);
2323

2424
/// <summary>
25-
/// Optional: The TimeZone in which the Cron expression should be based on.
26-
/// Defaults to UTC (Europe/London or GMT Standard Time)
27-
///
28-
/// NB! When overriding this and targeting versions below .NET 6, use platform specific identifiers
29-
/// If your runtime is .NET 6 or above, it's not required. It will handles the conversion:
30-
/// See https://github.com/dotnet/runtime/pull/49412
25+
/// Optional: The TimeZone in which the Cron expression should be based on.
26+
/// Defaults to UTC (Europe/London or GMT Standard Time)
27+
/// NB! When overriding this and targeting versions below .NET 6, use platform specific identifiers
28+
/// If your runtime is .NET 6 or above, it's not required. It will handles the conversion:
29+
/// See https://github.com/dotnet/runtime/pull/49412
3130
/// </summary>
3231
/// <returns>timezoneId</returns>
3332
string GetTimeZoneId()

src/CronBackgroundServices/Timing.cs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,9 @@
22

33
namespace CronBackgroundServices;
44

5-
internal class Timing
5+
internal class Timing(string timeZoneId)
66
{
7-
public readonly TimeZoneInfo TimeZoneInfo;
8-
9-
public Timing(string timeZoneId)
10-
{
11-
TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
12-
}
7+
public readonly TimeZoneInfo TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
138

149
public DateTimeOffset RelativeNow(DateTimeOffset? nowutc = null)
1510
{
@@ -27,11 +22,13 @@ public IEnumerable<string> Get10NextOccurrences(string cron)
2722
var expression = CronExpression.Parse(cron, CronFormat.IncludeSeconds);
2823
var fromUtc = DateTime.UtcNow;
2924
var upcoming = new List<DateTime>();
30-
upcoming.AddRange(Get10Occurrences(upcoming, expression, fromUtc, fromUtc.AddMonths(1)));
25+
upcoming.AddRange(GetTenNextsOccurrences(upcoming, expression, fromUtc, fromUtc.AddMonths(1)));
3126
return upcoming.Select(u => $"{u.ToLongDateString()} {u.ToLongTimeString()}");
3227
}
3328

34-
private IEnumerable<DateTime> Get10Occurrences(List<DateTime> upcoming, CronExpression expression, DateTime fromUtc, DateTime toUtc)
29+
private IEnumerable<DateTime> GetTenNextsOccurrences(List<DateTime> upcoming, CronExpression expression,
30+
DateTime fromUtc,
31+
DateTime toUtc)
3532
{
3633
while (true)
3734
{
@@ -43,9 +40,10 @@ private IEnumerable<DateTime> Get10Occurrences(List<DateTime> upcoming, CronExpr
4340
{
4441
continue;
4542
}
43+
4644
break;
4745
}
48-
return upcoming.Take(10);
4946

47+
return upcoming.Take(10);
5048
}
5149
}

0 commit comments

Comments
 (0)