diff --git a/Directory.Packages.props b/Directory.Packages.props
index 1423f5cd..ae3121b2 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -8,25 +8,27 @@
-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
+
+
+
-
-
-
+
+
+
diff --git a/THIRD-PARTY-NOTICES.md b/THIRD-PARTY-NOTICES.md
index ebe41a78..55ac799f 100644
--- a/THIRD-PARTY-NOTICES.md
+++ b/THIRD-PARTY-NOTICES.md
@@ -124,6 +124,38 @@ Licensed under the Apache License, Version 2.0.
Available at
https://github.com/MassTransit/MassTransit/blob/develop/LICENSE
+License notice for MassTransit.Extensions.Hosting
+------------------------------------
+
+Licensed under the Apache License, Version 2.0.
+Available at
+https://github.com/NCodeGroup/MassTransit.Extensions.Hosting/blob/master/LICENSE.txt
+
+License notice for Meziantou.Polyfill
+------------------------------------
+
+MIT License
+
+Copyright (c) Gérald Barré
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
License notice for Microsoft.NET.Test.Sdk
------------------------------------
@@ -187,31 +219,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[ https://www.opensource.org/licenses/bsd-license.php ]
-License notice for PolySharp
-------------------------------------
-
-MIT License
-
-Copyright (c) 2022 Sergio Pedri
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
License notice for Serilog
------------------------------------
diff --git a/props/common.props b/props/common.props
index 6cf6f111..ba3ee59a 100644
--- a/props/common.props
+++ b/props/common.props
@@ -22,7 +22,7 @@
See https://github.com/gehongyan/Kook.Net/releases
MIT
Logo_Small.png
- net10.0;net9.0;net8.0;net462;netstandard2.0;netstandard2.1
+ net10.0;net9.0;net8.0;net462;netstandard2.1;netstandard2.0
$(NoWarn);NU1803;NU1900
6
true
@@ -35,25 +35,31 @@
$(VersionPrefix)
$(VersionPrefix)-$(VersionSuffix)
+
+ $(DefineConstants);SUPPORTS_ASYNC_DISPOSABLE
+
true
-
-
-
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
-
+
-
-
-
-
+
+
+
+
diff --git a/src/Kook.Net.CardMarkup/CardMarkupSerializer.cs b/src/Kook.Net.CardMarkup/CardMarkupSerializer.cs
index faff03d1..e9d22ce5 100644
--- a/src/Kook.Net.CardMarkup/CardMarkupSerializer.cs
+++ b/src/Kook.Net.CardMarkup/CardMarkupSerializer.cs
@@ -22,11 +22,10 @@ public static class CardMarkupSerializer
/// 一个表示异步解析操作的任务。任务的结果包含一个可用于枚举 成员的 。
public static async Task> DeserializeAsync(FileInfo file, CancellationToken token = default)
{
-#if NETSTANDARD2_0 || NET462
- using FileStream fs = file.OpenRead();
-#else
- await using FileStream fs = file.OpenRead();
+#if SUPPORTS_ASYNC_DISPOSABLE
+ await
#endif
+ using FileStream fs = file.OpenRead();
return await DeserializeAsync(fs, token);
}
diff --git a/src/Kook.Net.Commands/Map/CommandMapNode.cs b/src/Kook.Net.Commands/Map/CommandMapNode.cs
index 3272a103..f658be6a 100644
--- a/src/Kook.Net.Commands/Map/CommandMapNode.cs
+++ b/src/Kook.Net.Commands/Map/CommandMapNode.cs
@@ -9,11 +9,7 @@ internal class CommandMapNode
private readonly ConcurrentDictionary _nodes;
private readonly string _name;
-#if NET9_0_OR_GREATER
private readonly Lock _lockObj = new();
-#else
- private readonly object _lockObj = new();
-#endif
private ImmutableArray _commands;
// ReSharper disable InconsistentlySynchronizedField
diff --git a/src/Kook.Net.Commands/PrimitiveParsers.cs b/src/Kook.Net.Commands/PrimitiveParsers.cs
index c5e7f6c3..ba7a91a0 100644
--- a/src/Kook.Net.Commands/PrimitiveParsers.cs
+++ b/src/Kook.Net.Commands/PrimitiveParsers.cs
@@ -28,7 +28,7 @@ private static IReadOnlyDictionary CreateParsers()
parserBuilder[typeof(DateTime)] = (TryParseDelegate)DateTime.TryParse;
parserBuilder[typeof(DateTimeOffset)] = (TryParseDelegate)DateTimeOffset.TryParse;
parserBuilder[typeof(Guid)] = (TryParseDelegate)Guid.TryParse;
-#if NET6_0_OR_GREATER
+#if NET
parserBuilder[typeof(DateOnly)] = (TryParseDelegate)DateOnly.TryParse;
parserBuilder[typeof(TimeOnly)] = (TryParseDelegate)TimeOnly.TryParse;
#endif
diff --git a/src/Kook.Net.Core/Extensions/CollectionExtensions.cs b/src/Kook.Net.Core/Extensions/CollectionExtensions.cs
index 636c41a6..7e5f3d54 100644
--- a/src/Kook.Net.Core/Extensions/CollectionExtensions.cs
+++ b/src/Kook.Net.Core/Extensions/CollectionExtensions.cs
@@ -5,61 +5,118 @@ namespace Kook;
internal static class CollectionExtensions
{
- //public static IReadOnlyCollection ToReadOnlyCollection(this IReadOnlyCollection source)
- // => new CollectionWrapper(source, () => source.Count);
+ // extension(IReadOnlyCollection source)
+ // {
+ // public IReadOnlyCollection ToReadOnlyCollection()
+ // => new CollectionWrapper(source, () => source.Count);
+ // }
- public static IReadOnlyCollection ToReadOnlyCollection(this ICollection source) =>
- new CollectionWrapper(source, () => source.Count);
+ extension(ICollection source)
+ {
+ public IReadOnlyCollection ToReadOnlyCollection() =>
+ new CollectionWrapper(source, () => source.Count);
+ }
+
+ // extension(IReadOnlyDictionary source)
+ // {
+ // public IReadOnlyCollection ToReadOnlyCollection()
+ // => new CollectionWrapper(source.Select(x => x.Value), () => source.Count);
+ // }
+
+ extension(IDictionary source)
+ {
+ public IReadOnlyCollection ToReadOnlyCollection() =>
+ new CollectionWrapper(source.Values, () => source.Count);
+ }
+
+ extension(IEnumerable query)
+ {
+ public IReadOnlyCollection ToReadOnlyCollection(IReadOnlyCollection source) =>
+ new CollectionWrapper(query, () => source.Count);
+
+ public IReadOnlyCollection ToReadOnlyCollection(Func countFunc) =>
+ new CollectionWrapper(query, countFunc);
- //public static IReadOnlyCollection ToReadOnlyCollection(this IReadOnlyDictionary source)
- // => new CollectionWrapper(source.Select(x => x.Value), () => source.Count);
+#if NETSTANDARD || NETFRAMEWORK
+ public IEnumerable Chunk(int size)
+ {
+ if (query is null)
+ throw new ArgumentNullException(nameof(query));
- public static IReadOnlyCollection ToReadOnlyCollection(this IDictionary source) =>
- new CollectionWrapper(source.Values, () => source.Count);
+ if (size <= 0)
+ throw new ArgumentOutOfRangeException(nameof(size));
- public static IReadOnlyCollection ToReadOnlyCollection(this IEnumerable query,
- IReadOnlyCollection source) =>
- new CollectionWrapper(query, () => source.Count);
+ return ChunkIterator(query, size);
- public static IReadOnlyCollection ToReadOnlyCollection(this IEnumerable query, Func countFunc) =>
- new CollectionWrapper(query, countFunc);
+ static IEnumerable ChunkIterator(IEnumerable source, int size)
+ {
+ using IEnumerator e = source.GetEnumerator();
-#if !NET6_0_OR_GREATER
- public static TSource? MinBy(
- this IEnumerable source,
- Func keySelector) =>
- source.OrderBy(keySelector).FirstOrDefault();
+ // Before allocating anything, make sure there's at least one element.
+ if (e.MoveNext())
+ {
+ // Now that we know we have at least one item, allocate an initial storage array. This is not
+ // the array we'll yield. It starts out small in order to avoid significantly overallocating
+ // when the source has many fewer elements than the chunk size.
+ int arraySize = Math.Min(size, 4);
+ int i;
+ do
+ {
+ TValue[]? array = new TValue[arraySize];
- public static TSource? MaxBy(
- this IEnumerable source,
- Func keySelector) =>
- source.OrderByDescending(keySelector).FirstOrDefault();
+ // Store the first item.
+ array[0] = e.Current;
+ i = 1;
- public static IEnumerable> Chunk(this IEnumerable source, int chunkSize) =>
- source
- .Select((x, i) => new { Index = i, Value = x })
- .GroupBy(x => x.Index / chunkSize)
- .Select(x => x.Select(v => v.Value));
+ if (size != array.Length)
+ {
+ // This is the first chunk. As we fill the array, grow it as needed.
+ for (; i < size && e.MoveNext(); i++)
+ {
+ if (i >= array.Length)
+ {
+ arraySize = (int)Math.Min((uint)size, 2 * (uint)array.Length);
+ Array.Resize(ref array, arraySize);
+ }
+
+ array[i] = e.Current;
+ }
+ }
+ else
+ {
+ // For all but the first chunk, the array will already be correctly sized.
+ // We can just store into it until either it's full or MoveNext returns false.
+ TValue[] local = array; // avoid bounds checks by using cached local (`array` is lifted to iterator object as a field)
+ for (; (uint)i < (uint)local.Length && e.MoveNext(); i++)
+ {
+ local[i] = e.Current;
+ }
+ }
+
+ if (i != array.Length)
+ {
+ Array.Resize(ref array, i);
+ }
+
+ yield return array;
+ }
+ while (i >= size && e.MoveNext());
+ }
+ }
+ }
#endif
+ }
}
[DebuggerDisplay("{DebuggerDisplay,nq}")]
-internal readonly struct CollectionWrapper : IReadOnlyCollection
+internal readonly struct CollectionWrapper
+ (IEnumerable query, Func countFunc) : IReadOnlyCollection
{
- private readonly IEnumerable _query;
- private readonly Func _countFunc;
-
//It's okay that this count is affected by race conditions - we're wrapping a concurrent collection and that's to be expected
- public int Count => _countFunc();
-
- public CollectionWrapper(IEnumerable query, Func countFunc)
- {
- _query = query;
- _countFunc = countFunc;
- }
+ public int Count => countFunc();
private string DebuggerDisplay => $"Count = {Count}";
- public IEnumerator GetEnumerator() => _query.GetEnumerator();
- IEnumerator IEnumerable.GetEnumerator() => _query.GetEnumerator();
+ public IEnumerator GetEnumerator() => query.GetEnumerator();
+ IEnumerator IEnumerable.GetEnumerator() => query.GetEnumerator();
}
diff --git a/src/Kook.Net.Core/GlobalUsings.cs b/src/Kook.Net.Core/GlobalUsings.cs
new file mode 100644
index 00000000..ed5439ff
--- /dev/null
+++ b/src/Kook.Net.Core/GlobalUsings.cs
@@ -0,0 +1,3 @@
+#if NETFRAMEWORK
+global using System.Net.Http;
+#endif
diff --git a/src/Kook.Net.Core/Kook.Net.Core.csproj b/src/Kook.Net.Core/Kook.Net.Core.csproj
index 19237bd4..53940773 100644
--- a/src/Kook.Net.Core/Kook.Net.Core.csproj
+++ b/src/Kook.Net.Core/Kook.Net.Core.csproj
@@ -7,10 +7,26 @@
The core definition library for Kook.Net.
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
diff --git a/src/Kook.Net.Core/Net/BucketId.cs b/src/Kook.Net.Core/Net/BucketId.cs
index 9b0b46e9..e4b0ebf0 100644
--- a/src/Kook.Net.Core/Net/BucketId.cs
+++ b/src/Kook.Net.Core/Net/BucketId.cs
@@ -1,7 +1,4 @@
using System.Diagnostics.CodeAnalysis;
-#if NET462
-using System.Net.Http;
-#endif
namespace Kook.Net;
diff --git a/src/Kook.Net.Core/Net/Rest/IRestClient.cs b/src/Kook.Net.Core/Net/Rest/IRestClient.cs
index ea9914f8..8d5c9017 100644
--- a/src/Kook.Net.Core/Net/Rest/IRestClient.cs
+++ b/src/Kook.Net.Core/Net/Rest/IRestClient.cs
@@ -1,7 +1,3 @@
-#if NET462
-using System.Net.Http;
-#endif
-
namespace Kook.Net.Rest;
///
diff --git a/src/Kook.Net.Core/Utils/AsyncEvent.cs b/src/Kook.Net.Core/Utils/AsyncEvent.cs
index 884bbd25..2a285172 100644
--- a/src/Kook.Net.Core/Utils/AsyncEvent.cs
+++ b/src/Kook.Net.Core/Utils/AsyncEvent.cs
@@ -5,11 +5,7 @@ namespace Kook;
internal class AsyncEvent
where T : class
{
-#if NET9_0_OR_GREATER
private readonly Lock _subLock = new();
-#else
- private readonly object _subLock = new();
-#endif
internal ImmutableArray _subscriptions = [];
// ReSharper disable once InconsistentlySynchronizedField
diff --git a/src/Kook.Net.Core/Utils/PolyfillUtils.cs b/src/Kook.Net.Core/Utils/PolyfillUtils.cs
new file mode 100644
index 00000000..a66bda1c
--- /dev/null
+++ b/src/Kook.Net.Core/Utils/PolyfillUtils.cs
@@ -0,0 +1,11 @@
+namespace Kook;
+
+internal static class PolyfillUtils
+{
+#if NETSTANDARD2_0 || NETFRAMEWORK
+ extension(DateTimeOffset)
+ {
+ public static DateTimeOffset UnixEpoch => new(621355968000000000L, TimeSpan.Zero);
+ }
+#endif
+}
diff --git a/src/Kook.Net.DependencyInjection.Microsoft/Kook.Net.DependencyInjection.Microsoft.csproj b/src/Kook.Net.DependencyInjection.Microsoft/Kook.Net.DependencyInjection.Microsoft.csproj
index be402cfc..5c0501f2 100644
--- a/src/Kook.Net.DependencyInjection.Microsoft/Kook.Net.DependencyInjection.Microsoft.csproj
+++ b/src/Kook.Net.DependencyInjection.Microsoft/Kook.Net.DependencyInjection.Microsoft.csproj
@@ -11,11 +11,11 @@
-
+
-
+
diff --git a/src/Kook.Net.Experimental/GlobalUsings.cs b/src/Kook.Net.Experimental/GlobalUsings.cs
new file mode 100644
index 00000000..ed5439ff
--- /dev/null
+++ b/src/Kook.Net.Experimental/GlobalUsings.cs
@@ -0,0 +1,3 @@
+#if NETFRAMEWORK
+global using System.Net.Http;
+#endif
diff --git a/src/Kook.Net.Experimental/Rest/KookRestApiClientExperimentalExtensions.cs b/src/Kook.Net.Experimental/Rest/KookRestApiClientExperimentalExtensions.cs
index e5af4888..946231e2 100644
--- a/src/Kook.Net.Experimental/Rest/KookRestApiClientExperimentalExtensions.cs
+++ b/src/Kook.Net.Experimental/Rest/KookRestApiClientExperimentalExtensions.cs
@@ -1,7 +1,3 @@
-#if NET462
-using System.Net.Http;
-#endif
-
using Kook.API;
using Kook.API.Rest;
using Kook.Net.Queue;
diff --git a/src/Kook.Net.Hosting/Kook.Net.Hosting.csproj b/src/Kook.Net.Hosting/Kook.Net.Hosting.csproj
index 452e5bf9..753d3557 100644
--- a/src/Kook.Net.Hosting/Kook.Net.Hosting.csproj
+++ b/src/Kook.Net.Hosting/Kook.Net.Hosting.csproj
@@ -11,11 +11,11 @@
-
+
-
+
diff --git a/src/Kook.Net.MessageQueue.InMemory/BufferedInMemoryMessageQueue.cs b/src/Kook.Net.MessageQueue.InMemory/BufferedInMemoryMessageQueue.cs
index 7e5e241a..81cc3da0 100644
--- a/src/Kook.Net.MessageQueue.InMemory/BufferedInMemoryMessageQueue.cs
+++ b/src/Kook.Net.MessageQueue.InMemory/BufferedInMemoryMessageQueue.cs
@@ -10,11 +10,7 @@ namespace Kook.Net.Queue.InMemory;
internal sealed class BufferedInMemoryMessageQueue : BaseMessageQueue
{
private readonly InMemoryMessageQueueOptions _options;
-#if NET9_0_OR_GREATER
private readonly Lock _lock = new();
-#else
- private readonly object _lock = new();
-#endif
private readonly SortedDictionary _buffer = new();
private readonly Channel _outputChannel;
private readonly int _maxSeq;
diff --git a/src/Kook.Net.Pipe/GlobalUsings.cs b/src/Kook.Net.Pipe/GlobalUsings.cs
new file mode 100644
index 00000000..ed5439ff
--- /dev/null
+++ b/src/Kook.Net.Pipe/GlobalUsings.cs
@@ -0,0 +1,3 @@
+#if NETFRAMEWORK
+global using System.Net.Http;
+#endif
diff --git a/src/Kook.Net.Pipe/KookPipeClient.cs b/src/Kook.Net.Pipe/KookPipeClient.cs
index bb89a54c..34009f52 100644
--- a/src/Kook.Net.Pipe/KookPipeClient.cs
+++ b/src/Kook.Net.Pipe/KookPipeClient.cs
@@ -7,10 +7,6 @@
using Kook.Logging;
using Kook.Rest;
-#if NET462
-using System.Net.Http;
-#endif
-
namespace Kook.Pipe;
///
@@ -232,7 +228,7 @@ private static NameValueCollection ParseQueryString(Uri url)
if (string.IsNullOrWhiteSpace(url.Query))
throw new ArgumentNullException(nameof(url), "The given pipe URL does not contain a query string.");
-#if NET462
+#if NETFRAMEWORK
NameValueCollection collection = [];
foreach (string queryItem in url.Query.TrimStart('?').Split('&'))
{
diff --git a/src/Kook.Net.Rest/BaseKookClient.cs b/src/Kook.Net.Rest/BaseKookClient.cs
index 44bcad7a..b8d3d266 100644
--- a/src/Kook.Net.Rest/BaseKookClient.cs
+++ b/src/Kook.Net.Rest/BaseKookClient.cs
@@ -1,7 +1,3 @@
-#if NET462
-using System.Net.Http;
-#endif
-
using System.Collections.Immutable;
using Kook.Logging;
@@ -172,7 +168,7 @@ internal virtual async Task LoginInternalAsync(TokenType tokenType, string token
}
catch (ArgumentException ex)
{
- // log these ArgumentExceptions and allow for the client to attempt to log in anyways
+ // log these ArgumentExceptions and allow for the client to attempt to log in any ways
await LogManager.WarningAsync("Kook", "A supplied token was invalid.", ex).ConfigureAwait(false);
}
}
diff --git a/src/Kook.Net.Rest/Entities/Messages/MessageHelper.cs b/src/Kook.Net.Rest/Entities/Messages/MessageHelper.cs
index dac90c83..4c3f649f 100644
--- a/src/Kook.Net.Rest/Entities/Messages/MessageHelper.cs
+++ b/src/Kook.Net.Rest/Entities/Messages/MessageHelper.cs
@@ -491,10 +491,10 @@ public static ImmutableArray ParseTags(string text, IMessageChannel? chann
_ => throw new ArgumentOutOfRangeException(nameof(tagMode), tagMode, null)
};
-#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
- foreach (Match match in matchCollection.Where(m => m.Success))
-#else
+#if NETSTANDARD2_0 || NETFRAMEWORK
foreach (Match match in matchCollection.Cast().Where(m => m.Success))
+#else
+ foreach (Match match in matchCollection.Where(m => m.Success))
#endif
{
index = match.Index;
diff --git a/src/Kook.Net.Rest/GlobalUsings.cs b/src/Kook.Net.Rest/GlobalUsings.cs
new file mode 100644
index 00000000..ed5439ff
--- /dev/null
+++ b/src/Kook.Net.Rest/GlobalUsings.cs
@@ -0,0 +1,3 @@
+#if NETFRAMEWORK
+global using System.Net.Http;
+#endif
diff --git a/src/Kook.Net.Rest/Kook.Net.Rest.csproj b/src/Kook.Net.Rest/Kook.Net.Rest.csproj
index a29571bf..64f8c6b3 100644
--- a/src/Kook.Net.Rest/Kook.Net.Rest.csproj
+++ b/src/Kook.Net.Rest/Kook.Net.Rest.csproj
@@ -1,5 +1,5 @@
-
+
Kook.Rest
true
@@ -7,15 +7,6 @@
The REST API implementation for Kook.Net.
-
+
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
diff --git a/src/Kook.Net.Rest/KookRestApiClient.cs b/src/Kook.Net.Rest/KookRestApiClient.cs
index 164cab6d..1cc1f716 100644
--- a/src/Kook.Net.Rest/KookRestApiClient.cs
+++ b/src/Kook.Net.Rest/KookRestApiClient.cs
@@ -1,7 +1,3 @@
-#if NET462
-using System.Net.Http;
-#endif
-
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
@@ -1965,7 +1961,7 @@ protected void CheckState()
[return: NotNullIfNotNull(nameof(content))]
protected static string? UrlEncode(string? content)
{
-#if NET462
+#if NETFRAMEWORK
return System.Net.WebUtility.UrlEncode(content);
#else
return System.Web.HttpUtility.UrlEncode(content);
diff --git a/src/Kook.Net.Rest/KookRestClient.cs b/src/Kook.Net.Rest/KookRestClient.cs
index bc13bb00..d5f9772f 100644
--- a/src/Kook.Net.Rest/KookRestClient.cs
+++ b/src/Kook.Net.Rest/KookRestClient.cs
@@ -316,12 +316,12 @@ public Task RemoveDirectMessageReactionAsync(Guid messageId, ulong userId, IEmot
/// 一个表示异步创建操作的任务。任务的结果是上传文件后的资源地址 URL。
public async Task CreateAssetAsync(string path, string? filename = null, RequestOptions? options = null)
{
-#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
- await using FileStream fileStream = File.OpenRead(path);
-#else
- using FileStream fileStream = File.OpenRead(path);
+#if SUPPORTS_ASYNC_DISPOSABLE
+ await
#endif
- return await ClientHelper.CreateAssetAsync(this, fileStream, filename ?? Path.GetFileName(path), options)
+ using FileStream fileStream = File.OpenRead(path);
+ return await ClientHelper
+ .CreateAssetAsync(this, fileStream, filename ?? Path.GetFileName(path), options)
.ConfigureAwait(false);
}
diff --git a/src/Kook.Net.Rest/Net/Converters/DateTimeOffsetUnixTimeMillisecondsConverter.cs b/src/Kook.Net.Rest/Net/Converters/DateTimeOffsetUnixTimeMillisecondsConverter.cs
index 72ef53fc..41835dd4 100644
--- a/src/Kook.Net.Rest/Net/Converters/DateTimeOffsetUnixTimeMillisecondsConverter.cs
+++ b/src/Kook.Net.Rest/Net/Converters/DateTimeOffsetUnixTimeMillisecondsConverter.cs
@@ -10,11 +10,7 @@ public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConver
public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
{
-#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
if (value == DateTimeOffset.MinValue || value == DateTimeOffset.UnixEpoch)
-#else
- if (value == DateTimeOffset.MinValue || value == new DateTimeOffset(621355968000000000L, TimeSpan.Zero))
-#endif
writer.WriteNullValue();
else
writer.WriteNumberValue(value.ToUnixTimeMilliseconds());
diff --git a/src/Kook.Net.Rest/Net/Converters/DateTimeOffsetUnixTimeSecondsConverter.cs b/src/Kook.Net.Rest/Net/Converters/DateTimeOffsetUnixTimeSecondsConverter.cs
index 13798982..88cfa4e5 100644
--- a/src/Kook.Net.Rest/Net/Converters/DateTimeOffsetUnixTimeSecondsConverter.cs
+++ b/src/Kook.Net.Rest/Net/Converters/DateTimeOffsetUnixTimeSecondsConverter.cs
@@ -10,11 +10,7 @@ public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConver
public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
{
-#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
if (value == DateTimeOffset.MinValue || value == DateTimeOffset.UnixEpoch)
-#else
- if (value == DateTimeOffset.MinValue || value == new DateTimeOffset(621355968000000000L, TimeSpan.Zero))
-#endif
writer.WriteNullValue();
else
writer.WriteNumberValue(value.ToUnixTimeSeconds());
diff --git a/src/Kook.Net.Rest/Net/Converters/NullableDateTimeOffsetUnixTimeMillisecondsConverter.cs b/src/Kook.Net.Rest/Net/Converters/NullableDateTimeOffsetUnixTimeMillisecondsConverter.cs
index b9f68032..2c4ca27c 100644
--- a/src/Kook.Net.Rest/Net/Converters/NullableDateTimeOffsetUnixTimeMillisecondsConverter.cs
+++ b/src/Kook.Net.Rest/Net/Converters/NullableDateTimeOffsetUnixTimeMillisecondsConverter.cs
@@ -21,11 +21,7 @@ internal class NullableDateTimeOffsetUnixTimeMillisecondsConverter : JsonConvert
public override void Write(Utf8JsonWriter writer, DateTimeOffset? value, JsonSerializerOptions options)
{
-#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
if (!value.HasValue || value == DateTimeOffset.MinValue || value == DateTimeOffset.UnixEpoch)
-#else
- if (!value.HasValue || value == DateTimeOffset.MinValue || value == new DateTimeOffset(621355968000000000L, TimeSpan.Zero))
-#endif
writer.WriteNullValue();
else
writer.WriteNumberValue(value.Value.ToUnixTimeMilliseconds());
diff --git a/src/Kook.Net.Rest/Net/Converters/NullableDateTimeOffsetUnixTimeSecondsConverter.cs b/src/Kook.Net.Rest/Net/Converters/NullableDateTimeOffsetUnixTimeSecondsConverter.cs
index 867a05cf..a84d47c3 100644
--- a/src/Kook.Net.Rest/Net/Converters/NullableDateTimeOffsetUnixTimeSecondsConverter.cs
+++ b/src/Kook.Net.Rest/Net/Converters/NullableDateTimeOffsetUnixTimeSecondsConverter.cs
@@ -21,11 +21,7 @@ internal class NullableDateTimeOffsetUnixTimeSecondsConverter : JsonConverter
diff --git a/src/Kook.Net.WebSocket/Kook.Net.WebSocket.csproj b/src/Kook.Net.WebSocket/Kook.Net.WebSocket.csproj
index f2d4e984..291f1d55 100644
--- a/src/Kook.Net.WebSocket/Kook.Net.WebSocket.csproj
+++ b/src/Kook.Net.WebSocket/Kook.Net.WebSocket.csproj
@@ -11,7 +11,4 @@
-
-
-
-
\ No newline at end of file
+
diff --git a/src/Kook.Net.WebSocket/KookSocketApiClient.cs b/src/Kook.Net.WebSocket/KookSocketApiClient.cs
index 547d9e01..95b40d3c 100644
--- a/src/Kook.Net.WebSocket/KookSocketApiClient.cs
+++ b/src/Kook.Net.WebSocket/KookSocketApiClient.cs
@@ -80,19 +80,17 @@ public KookSocketApiClient(RestClientProvider restClientProvider,
private async Task OnBinaryMessage(byte[] data, int index, int count)
{
-#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
- await using MemoryStream decompressed = new();
-#else
- using MemoryStream decompressed = new();
+#if SUPPORTS_ASYNC_DISPOSABLE
+ await
#endif
+ using MemoryStream decompressed = new();
using MemoryStream compressed = data[0] == 0x78
? new MemoryStream(data, index + 2, count - 2)
: new MemoryStream(data, index, count);
-#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
- await using DeflateStream decompressor = new(compressed, CompressionMode.Decompress);
-#else
- using DeflateStream decompressor = new(compressed, CompressionMode.Decompress);
+#if SUPPORTS_ASYNC_DISPOSABLE
+ await
#endif
+ using DeflateStream decompressor = new(compressed, CompressionMode.Decompress);
await decompressor.CopyToAsync(decompressed);
decompressed.Position = 0;
diff --git a/src/Kook.Net.Webhook.HttpListener/Net/HttpListener/HttpListenerWebhookClient.cs b/src/Kook.Net.Webhook.HttpListener/Net/HttpListener/HttpListenerWebhookClient.cs
index 0c49a3ce..4a8a225e 100644
--- a/src/Kook.Net.Webhook.HttpListener/Net/HttpListener/HttpListenerWebhookClient.cs
+++ b/src/Kook.Net.Webhook.HttpListener/Net/HttpListener/HttpListenerWebhookClient.cs
@@ -197,20 +197,16 @@ private async Task HandleRequestAsync(HttpListenerContext context)
if (context.Request.QueryString["compress"]?.Split(',').Any(x => x.StartsWith("0")) is true)
{
using StreamReader streamReader = new(context.Request.InputStream);
-#if NET7_0_OR_GREATER
string requestBody = await streamReader.ReadToEndAsync(_cancellationToken);
-#else
- string requestBody = await streamReader.ReadToEndAsync();
-#endif
messageResponse = await HandleTextMessageAsync(requestBody);
}
else
{
using MemoryStream stream = new();
-#if NET7_0_OR_GREATER
- await context.Request.InputStream.CopyToAsync(stream, _cancellationToken);
-#else
+#if NETSTANDARD2_0 || NETFRAMEWORK
await context.Request.InputStream.CopyToAsync(stream);
+#else
+ await context.Request.InputStream.CopyToAsync(stream, _cancellationToken);
#endif
byte[] bytes = stream.ToArray();
messageResponse = await HandleBinaryMessageAsync(bytes, 0, bytes.Length);
@@ -218,21 +214,16 @@ private async Task HandleRequestAsync(HttpListenerContext context)
if (messageResponse is not null)
{
-#if NETSTANDARD2_0 || NET462
- using StreamWriter writer = new(context.Response.OutputStream);
-#else
- await using StreamWriter writer = new(context.Response.OutputStream);
+#if SUPPORTS_ASYNC_DISPOSABLE
+ await
#endif
+ using StreamWriter writer = new(context.Response.OutputStream);
await writer.WriteAsync(messageResponse);
}
else
{
context.Response.StatusCode = (int)HttpStatusCode.NoContent;
-#if NETSTANDARD2_0 || NET462
- await context.Response.OutputStream.WriteAsync([], 0, 0, _cancellationToken);
-#else
await context.Response.OutputStream.WriteAsync(ReadOnlyMemory.Empty, _cancellationToken);
-#endif
}
}
catch
diff --git a/src/Kook.Net.Webhook/KookWebhookApiClient.cs b/src/Kook.Net.Webhook/KookWebhookApiClient.cs
index ea99aa53..2517d6c0 100644
--- a/src/Kook.Net.Webhook/KookWebhookApiClient.cs
+++ b/src/Kook.Net.Webhook/KookWebhookApiClient.cs
@@ -58,27 +58,24 @@ public KookWebhookApiClient(RestClientProvider restClientProvider,
private async Task OnBinaryMessage(byte[] data, int index, int count)
{
-#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
- await using MemoryStream decompressed = new();
-#else
+#if SUPPORTS_ASYNC_DISPOSABLE
+ await
+#endif
using MemoryStream decompressed = new();
+#if SUPPORTS_ASYNC_DISPOSABLE
+ await
#endif
using MemoryStream compressed = data[0] == 0x78
? new MemoryStream(data, index + 2, count - 2)
: new MemoryStream(data, index, count);
-#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
- await using DeflateStream decompressor = new(compressed, CompressionMode.Decompress);
-#else
- using DeflateStream decompressor = new(compressed, CompressionMode.Decompress);
+#if SUPPORTS_ASYNC_DISPOSABLE
+ await
#endif
+ using DeflateStream decompressor = new(compressed, CompressionMode.Decompress);
await decompressor.CopyToAsync(decompressed);
decompressed.Position = 0;
-#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
GatewayEncryptedFrame? gatewayEncryptedFrame = await JsonSerializer.DeserializeAsync(decompressed, _serializerOptions);
-#else
- GatewayEncryptedFrame? gatewayEncryptedFrame = JsonSerializer.Deserialize(decompressed, _serializerOptions);
-#endif
if (gatewayEncryptedFrame is null)
return null;
string decryptedFrame = Decrypt(gatewayEncryptedFrame.Encrypted, _encryptKey);
diff --git a/test/Kook.Net.Tests.Unit/ModuleBuilderTests.cs b/test/Kook.Net.Tests.Unit/ModuleBuilderTests.cs
index 9dfe1227..6a054042 100644
--- a/test/Kook.Net.Tests.Unit/ModuleBuilderTests.cs
+++ b/test/Kook.Net.Tests.Unit/ModuleBuilderTests.cs
@@ -581,11 +581,7 @@ public void CountdownModuleBuilder_InvalidTimes()
yield return (CountdownMode.Day, DateTimeOffset.Now.AddDays(-1), null);
yield return (CountdownMode.Hour, DateTimeOffset.Now.AddDays(-1), null);
// StartTime must be equal or later than Unix Epoch
-#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
yield return (CountdownMode.Second, DateTimeOffset.Now.AddMinutes(1), DateTimeOffset.UnixEpoch.AddTicks(-1));
-#else
- yield return (CountdownMode.Second, DateTimeOffset.Now.AddMinutes(1), new DateTimeOffset(621355968000000000L, TimeSpan.Zero).AddTicks(-1));
-#endif
// EndTime must be later than StartTime
yield return (CountdownMode.Second, DateTimeOffset.Now.AddMinutes(1), DateTimeOffset.Now.AddMinutes(1));
yield return (CountdownMode.Second, DateTimeOffset.Now.AddMinutes(1), DateTimeOffset.Now.AddMinutes(2));