Skip to content

Commit cd227b6

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

File tree

2 files changed

+85
-1
lines changed

2 files changed

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

0 commit comments

Comments
 (0)