-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTypeManipulation.cs
133 lines (118 loc) · 7.45 KB
/
TypeManipulation.cs
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
using System;
using System.Reflection.Emit;
using JetBrains.Annotations;
namespace ILGeneratorExtensions
{
/// <summary>
/// Contains extension methods for dealing with the manipulation of the type of objects on the stack
/// </summary>
[PublicAPI]
public static class TypeManipulation
{
/// <summary>
/// Pops a reference from the evaluation stack, and pushes a reference of the given type if the object is an instance of that type, otherwise the null reference is pushed
/// </summary>
/// <typeparam name="T">The type to attempt to cast to</typeparam>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
[PublicAPI]
public static ILGenerator IsInstanceOfType<T>(this ILGenerator generator) => generator.IsInstanceOfType(typeof(T));
/// <summary>
/// Pops a reference from the evaluation stack, and pushes a reference of the given type if the object is an instance of the given type, otherwise the null reference is pushed
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
/// <param name="type">The type to attempt to cast to</param>
[PublicAPI]
public static ILGenerator IsInstanceOfType(this ILGenerator generator, Type type) => generator.FluentEmit(OpCodes.Isinst, type);
/// <summary>
/// Pops a reference from the evaluation stack, and pushes a reference of the given type if the object is an instance of that type, otherwise an <see cref="InvalidCastException" /> is thrown
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
/// <param name="type">The type to attempt to cast to</param>
[PublicAPI]
public static ILGenerator CastClass(this ILGenerator generator, Type type)
{
if (type.IsValueType)
{
throw new InvalidOperationException("Cannot cast to a value type");
}
return generator.FluentEmit(OpCodes.Castclass, type);
}
/// <summary>
/// Pops a reference from the evaluation stack, and pushes a reference of the given type if the object is an instance of that type, otherwise an <see cref="InvalidCastException" /> is thrown
/// </summary>
/// <typeparam name="T">The type to attempt to cast to</typeparam>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
[PublicAPI]
public static ILGenerator CastClass<T>(this ILGenerator generator) where T : class => generator.CastClass(typeof (T));
/// <summary>
/// Pops a value type object from the evaluation stack, and pushes a reference to a new boxed instance of the object onto the evaluation stack
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
/// <param name="type">The type of the value type object</param>
[PublicAPI]
public static ILGenerator Box(this ILGenerator generator, Type type)
{
if (!type.IsValueType)
{
throw new InvalidOperationException("Can only box value types");
}
return generator.FluentEmit(OpCodes.Box, type);
}
/// <summary>
/// Pops a value type object from the evaluation stack, and pushes a reference to a new boxed instance of the object onto the evaluation stack
/// </summary>
/// <typeparam name="T">The type of the value type object</typeparam>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
[PublicAPI]
public static ILGenerator Box<T>(this ILGenerator generator) where T : struct => generator.Box(typeof (T));
/// <summary>
/// Pops a reference from the evaluation stack, and pushes the address of the boxed value type of the given type
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
/// <param name="type">The type of the boxed value type</param>
[PublicAPI]
public static ILGenerator Unbox(this ILGenerator generator, Type type)
{
if (!type.IsValueType)
{
throw new InvalidOperationException("Cannot unbox non-value types");
}
return generator.FluentEmit(OpCodes.Unbox, type);
}
/// <summary>
/// Pops a reference from the evaluation stack, and pushes the address of the boxed value type of the given type
/// </summary>
/// <typeparam name="T">The type of the boxed value type</typeparam>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
[PublicAPI]
public static ILGenerator Unbox<T>(this ILGenerator generator) where T : struct => generator.Unbox(typeof (T));
/// <summary>
/// Pops a reference from the evaluation stack, and pushes the value type object if the object is a boxed value type, or a reference of the given type if the object is a reference type and is an instance of that type
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
/// <param name="type">The type to unbox to</param>
[PublicAPI]
public static ILGenerator UnboxAny(this ILGenerator generator, Type type) => generator.FluentEmit(OpCodes.Unbox_Any, type);
/// <summary>
/// Pops a reference from the evaluation stack, and pushes the value type object if the object is a boxed value type, or a reference of the given type if the object is a reference type and is an instance of that type
/// </summary>
/// <typeparam name="T">The type to unbox to</typeparam>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
[PublicAPI]
public static ILGenerator UnboxAny<T>(this ILGenerator generator) => generator.UnboxAny(typeof (T));
/// <summary>
/// Pushes the number of bytes required to store the given type, for reference types this will always be the size of a reference, not the size of an object of that type itself
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
/// <param name="type">The type to get the size of</param>
[PublicAPI]
public static ILGenerator SizeOf(this ILGenerator generator, Type type) => generator.FluentEmit(OpCodes.Sizeof, type);
/// <summary>
/// Pushes the number of bytes required to store the given type, for reference types this will always be the size of a reference, not the size of an object of that type itself
/// </summary>
/// <typeparam name="T">The type to get the size of</typeparam>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
[PublicAPI]
public static ILGenerator SizeOf<T>(this ILGenerator generator) => generator.SizeOf(typeof(T));
}
}