-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathReflectionCache.cs
More file actions
73 lines (57 loc) · 2.62 KB
/
ReflectionCache.cs
File metadata and controls
73 lines (57 loc) · 2.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using System;
using System.Linq.Expressions;
using System.Management.Automation;
using System.Reflection;
namespace ClassExplorer;
internal static class ReflectionCache
{
private static readonly Type? ExecutionContextType;
private static readonly MethodInfo? GetExecutionContextFromTLSMethod;
private static readonly Func<string[]>? GetUsingNamespacesFunc;
static ReflectionCache()
{
ExecutionContextType = typeof(PSObject).Assembly.GetType("System.Management.Automation.ExecutionContext");
if (ExecutionContextType is null) return;
GetExecutionContextFromTLSMethod = typeof(PSObject).Assembly.GetType("System.Management.Automation.Runspaces.LocalPipeline")
?.GetMethod("GetExecutionContextFromTLS", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
if (GetExecutionContextFromTLSMethod is null) return;
GetUsingNamespacesFunc = CreateGetUsingNamespaces();
}
public static string[] GetUsingNamespacesFromTLS()
{
return GetUsingNamespacesFunc?.Invoke() ?? ["System"];
}
private static Func<string[]>? CreateGetUsingNamespaces()
{
const BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
if (GetExecutionContextFromTLSMethod is null) return null;
MethodInfo? getEngineSessionState = ExecutionContextType
?.GetProperty("EngineSessionState", flags)
?.GetGetMethod(nonPublic: true);
if (getEngineSessionState is null) return null;
MethodInfo? currentScope = getEngineSessionState?.ReturnType
?.GetProperty("CurrentScope", flags)
?.GetGetMethod(nonPublic: true);
if (currentScope is null) return null;
MethodInfo? typeRes = currentScope?.ReturnType
?.GetProperty("TypeResolutionState", flags)
?.GetGetMethod(nonPublic: true);
if (typeRes is null) return null;
FieldInfo? namespaces = typeRes.GetReturnType()?.GetField("namespaces", flags);
if (namespaces is null) return null;
if (namespaces.FieldType != typeof(string[])) return null;
return Expression.Lambda<Func<string[]>>(
Expression.Field(
Expression.Call(
Expression.Call(
Expression.Call(
Expression.Call(GetExecutionContextFromTLSMethod),
getEngineSessionState!),
currentScope!),
typeRes),
namespaces),
"GetUsingNamespacesDynamically",
[])
.Compile();
}
}