forked from mdsol/FastAndFaster
/
Initializer.cs
66 lines (57 loc) · 2.58 KB
/
Initializer.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
using FastAndFaster.Helpers;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Reflection;
using System.Reflection.Emit;
namespace FastAndFaster
{
public static class Initializer
{
/// <summary>
/// Sliding cache expiration time for delegates to call a public constructor of a class.
/// The unit is second and the default value is 43,200 (12 hours).
/// </summary>
public static int SlidingExpirationInSecs { get; set; } = 12 * 3600;
private const byte CONSTRUCTOR_LOAD_INDEX = 0;
private static readonly MemoryCache _cache = new MemoryCache(new MemoryCacheOptions());
/// <summary>
/// Create a delegate to call a public constructor of a class.
/// </summary>
/// <param name="typeName">
/// The assembly qualified name of the target class.
/// </param>
/// <param name="parameterTypes">
/// The list of the method's parameter types. For a parameterless method, this value can be omitted.
/// </param>
/// <returns>
/// A delegate to invoke the target method. The delegate type is Func<object[], object>.
/// </returns>
public static Func<object[], object> Create(string typeName, Type[] parameterTypes = null)
{
if (parameterTypes is null)
{
parameterTypes = Type.EmptyTypes;
}
var key = (typeName, TypeHelper.GetParameterTypesIdentity(parameterTypes));
return _cache.GetOrCreate(key, entry =>
{
entry.SlidingExpiration = TimeSpan.FromSeconds(SlidingExpirationInSecs);
var type = TypeHelper.GetTypeByName(typeName);
var delegateParameterTypes = new[] { typeof(object[]) };
var dynCtor = new DynamicMethod(
$"{type.FullName}_{TypeHelper.GetParameterTypesIdentity(parameterTypes)}_ctor",
type, delegateParameterTypes, true);
var ctorInfo = TypeHelper.GetConstructorInfoByType(type, parameterTypes);
GenerateIL(dynCtor, ctorInfo, parameterTypes);
return (Func<object[], object>)dynCtor.CreateDelegate(typeof(Func<object[], object>));
});
}
private static void GenerateIL(
DynamicMethod dynCtor, ConstructorInfo ctorInfo, Type[] parameterTypes)
{
var il = dynCtor.GetILGenerator();
IlHelper.LoadArguments(il, CONSTRUCTOR_LOAD_INDEX, parameterTypes);
IlHelper.CreateInstance(il, ctorInfo);
}
}
}