-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathUnitTest.cs
137 lines (118 loc) · 4.32 KB
/
UnitTest.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
134
135
136
137
using System.Diagnostics;
using System.Reflection;
using Antelcat.IL.Extensions;
namespace Antelcat.IL.Test;
public class RefClass
{
public static int Count = 0;
private readonly int Number = ++Count;
public override string ToString() => $"This is RefClass No.{Number}";
}
public class TestClass
{
public RefClass RefProp { get; set; }
public RefClass RefField;
public int ValueProp { get; set; } = 0;
public int ValueField = 0;
public static RefClass StaticRefProp { get; set; } = new();
public static RefClass StaticRefField = new();
public static int StaticValueProp { get; set; } = 0;
public static int StaticValueField = 0;
public static int StaticMethod(int value, out int result)
{
result = value++;
return value;
}
public int Method(ref int value) => --value;
}
public static class ConsoleExtension
{
public static void WriteLine(this object? o) => Console.WriteLine(o);
}
public class Tests
{
public static Type Type = typeof(TestClass);
[SetUp]
public void Setup()
{
}
[Test]
public void TestCtor()
{
Type.GetConstructors()[0].CreateCtor().Invoke().WriteLine();
}
[Test]
public void TestInvoke()
{
var method = Type.GetMethod(nameof(TestClass.Method))!.CreateInvoker();
method.Invoke(new TestClass(), 1).WriteLine();
method = Type.GetMethod(nameof(TestClass.StaticMethod))!.CreateInvoker();
var args = new object?[] { 1, null };
method.Invoke(null, args).WriteLine();
Debugger.Break();
}
[Test]
public void TestValueType()
{
var Prefix = "Value";
var prop = Type.GetProperty($"{Prefix}Prop")!;
var field = Type.GetField($"{Prefix}Field")!;
var i = 1;
TestGetterAndSetter(new TestClass(), prop, field, () => i++);
}
[Test]
public void TestRefType()
{
var Prefix = "Ref";
var prop = Type.GetProperty($"{Prefix}Prop")!;
var field = Type.GetField($"{Prefix}Field")!;
TestGetterAndSetter(new TestClass(), prop, field, () => new RefClass());
}
public void TestGetterAndSetter<TTarget, TValue>(TTarget? instance, PropertyInfo prop, FieldInfo field, Func<TValue> valueGetter)
{
var objInst = (object?)instance;
prop.CreateSetter<TTarget, object>().Invoke(ref instance, valueGetter());
prop.CreateGetter<TTarget, object>().Invoke(instance).WriteLine();
prop.CreateSetter<TTarget, TValue>().Invoke(ref instance, valueGetter());
prop.CreateGetter<TTarget, TValue>().Invoke(instance).WriteLine();
prop.CreateSetter<object, TValue>().Invoke(ref objInst, valueGetter());
prop.CreateGetter<object, TValue>().Invoke(instance).WriteLine();
prop.CreateSetter<object, object>().Invoke(ref objInst, valueGetter());
prop.CreateGetter<object, object>().Invoke(instance).WriteLine();
field.CreateSetter<TTarget, TValue>().Invoke(ref instance, valueGetter());
field.CreateGetter<TTarget, TValue>().Invoke(instance).WriteLine();
field.CreateSetter<TTarget, object>().Invoke(ref instance, valueGetter());
field.CreateGetter<TTarget, object>().Invoke(instance).WriteLine();
field.CreateSetter<object, TValue>().Invoke(ref objInst, valueGetter());
field.CreateGetter<object, TValue>().Invoke(instance).WriteLine();
field.CreateSetter<object, object>().Invoke(ref objInst, valueGetter());
field.CreateGetter<object, object>().Invoke(instance).WriteLine();
Debugger.Break();
}
[Test]
public void TestPerformance()
{
var method = Type.GetMethod($"{nameof(TestClass.Method)}")!;
var args = new object?[] { 1 };
var target = new TestClass();
var times = 1000;
var watch = new Stopwatch();
watch.Start();
while (times -- > 0)
{
method.Invoke(target, args);
}
watch.Stop();
Console.WriteLine($"Reflect cost {watch.ElapsedTicks} ticks");
var del = method.CreateInvoker();
watch = new Stopwatch();
watch.Start();
times = 1000;
while (times -- > 0)
{
del.Invoke(target, args);
}
watch.Stop();
Console.WriteLine($"IL cost {watch.ElapsedTicks} ticks");
}
}