Skip to content

Commit 03618cb

Browse files
committed
Use a workaround class To replace AsyncLocal
1 parent c42f356 commit 03618cb

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

ASFFreeGames/ASFFreeGamesPlugin.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ internal static PluginContext Context {
4040
}
4141

4242
// ReSharper disable once InconsistentNaming
43-
private static readonly ThreadLocal<PluginContext> _context = new();
43+
private static readonly Utils.Workarounds.AsyncLocal<PluginContext> _context = new();
4444
private static CancellationToken CancellationToken => Context.CancellationToken;
4545

4646
public string Name => StaticName;
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System;
2+
3+
namespace Maxisoft.ASF.Utils.Workarounds;
4+
5+
public sealed class AsyncLocal<T> {
6+
// ReSharper disable once StaticMemberInGenericType
7+
private static readonly Type? AsyncLocalType;
8+
9+
#pragma warning disable CA1810
10+
static AsyncLocal() {
11+
#pragma warning restore CA1810
12+
try {
13+
AsyncLocalType = Type.GetType("System.Threading.AsyncLocal`1")
14+
?.MakeGenericType(typeof(T));
15+
}
16+
catch (InvalidOperationException) {
17+
// ignore
18+
}
19+
20+
try {
21+
AsyncLocalType ??= Type.GetType("System.Threading.AsyncLocal")
22+
?.MakeGenericType(typeof(T));
23+
}
24+
25+
catch (InvalidOperationException) {
26+
// ignore
27+
}
28+
29+
AsyncLocalType ??= Type.GetType("System.Threading.AsyncLocal")
30+
?.MakeGenericType(typeof(T));
31+
}
32+
33+
private readonly dynamic? Delegate;
34+
private T? NonSafeValue;
35+
36+
/// <summary>Instantiates an <see cref="AsyncLocal{T}"/> instance that does not receive change notifications.</summary>
37+
public AsyncLocal() {
38+
if (AsyncLocalType is not null) {
39+
Delegate = Activator.CreateInstance(AsyncLocalType)!;
40+
}
41+
}
42+
43+
/// <summary>Gets or sets the value of the ambient data.</summary>
44+
/// <value>The value of the ambient data. If no value has been set, the returned value is default(T).</value>
45+
public T? Value {
46+
get {
47+
if (Delegate is not null) {
48+
try {
49+
return Delegate.Value;
50+
}
51+
catch (MissingMethodException) {
52+
// ignored
53+
}
54+
}
55+
56+
return (T) NonSafeValue!;
57+
}
58+
set {
59+
if (Delegate is not null) {
60+
try {
61+
Delegate.Value = value!;
62+
63+
return;
64+
}
65+
catch (MissingMethodException) {
66+
// ignored
67+
}
68+
}
69+
70+
NonSafeValue = value;
71+
}
72+
}
73+
}

0 commit comments

Comments
 (0)