This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static IReadOnlyList<FieldInfo> CollectFields(Delegate instance) | |
{ | |
// Local, recursive function to explore the closure type | |
IEnumerable<FieldInfo> CollectFields(Type type) | |
{ | |
foreach (FieldInfo field in type.GetFields()) | |
{ | |
if (field.Name.StartsWith("CS$<>")) // Nested closure type | |
{ | |
foreach (FieldInfo nested in CollectFields(field.FieldType)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static void Main() | |
{ | |
int[] array = new int[10]; | |
int value = 1; | |
Action<int> action = i => array[i] = value; | |
foreach (FieldInfo field in CollectFields(action)) | |
{ | |
Console.WriteLine($"{field.Name}: {field.GetValue(action.Target)}"); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public sealed class ClosureField | |
{ | |
public FieldInfo Info { get; } | |
public IReadOnlyList<FieldInfo> Parents { get; } | |
public ClosureField(FieldInfo info, IReadOnlyList<FieldInfo> parents) | |
{ | |
Info = info; | |
Parents = parents; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static void Main() | |
{ | |
int[] array = new int[10]; | |
{ | |
int value = 1; | |
Action<int> action = i => array[i] = value; | |
foreach (var field in CollectFields(action)) | |
{ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static unsafe (object[] References, byte[] Bytes) GetData( | |
Delegate instance, IReadOnlyList<ClosureField> fields) | |
{ | |
// Calculate how many bytes we need | |
int | |
referenceCount = 0, | |
byteSize = 0; | |
foreach (var field in fields) | |
{ | |
if (field.Info.FieldType.IsValueType) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# C# | |
public static object GetFieldXForVector2(object obj) | |
{ | |
Vector2 instance = (Vector2)obj; | |
return instance.X; | |
} | |
# IL (simplified) | |
public static object GetFieldXForVector2(object obj) | |
{ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// C# | |
public static int MultiplyAndAddOne(int a, int b) | |
{ | |
int temp = a * b; | |
return temp + 1; | |
} | |
// IL (simplified) | |
public static int32 MultiplyAndAddOne(int32 a, int32 b) | |
{ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private static Func<object, object> BuildDynamicGetter(ClosureField field) | |
{ | |
// Create a new dynamic method | |
Type ownerType = field.Info.DeclaringType; | |
DynamicMethod method = new DynamicMethod( | |
$"Get{field.Info.Name}", | |
typeof(object), // The return type | |
new [] { typeof(object) }, // A single object parameter | |
ownerType); // The type that will own the new method |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static Func<object, object> BuildDynamicGetter(ClosureField field) | |
{ | |
// Create a new dynamic method | |
FieldInfo[] hierarchy = field.Parents.Append(field.Info).ToArray(); | |
Type ownerType = hierarchy[0].DeclaringType; | |
DynamicMethod method = new DynamicMethod( | |
$"Get{field.Info.Name}", | |
typeof(object), // The return type | |
new[] { typeof(object) }, // A single object parameter | |
ownerType); // The type that will own the new method |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static void EmitStoreLocal(this ILGenerator il, int index) | |
{ | |
if (index <= 3) | |
{ | |
il.Emit(index switch | |
{ | |
0 => OpCodes.Stloc_0, | |
1 => OpCodes.Stloc_1, | |
2 => OpCodes.Stloc_2, | |
3 => OpCodes.Stloc_3, |