-
-
Notifications
You must be signed in to change notification settings - Fork 294
Expand file tree
/
Copy pathPropertyHelper.cs
More file actions
40 lines (34 loc) · 1.6 KB
/
PropertyHelper.cs
File metadata and controls
40 lines (34 loc) · 1.6 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
using System.Collections.Concurrent;
using System.Linq.Expressions;
using System.Reflection;
namespace MemoryPack;
public static class PropertyHelper
{
private static readonly ConcurrentDictionary<(Type Type, string FieldName), Delegate> _cache = new();
public static void SetInitOnlyProperty<T, TValue>(T instance, string propertyName, TValue newValue)
{
Type typeOfT = typeof(T);
var key = (typeOfT, propertyName);
if (!_cache.TryGetValue(key, out Delegate? setter))
{
var prop = typeOfT.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (prop is null)
{
throw new ArgumentException($"Property \"{propertyName}\" not found in type \"{typeOfT}\"");
}
var setMethod = prop.GetSetMethod(true);
if (setMethod is null)
{
throw new ArgumentException($"Property \"{propertyName}\" does not have a setter.");
}
setter = setMethod.CreateDelegate(typeof(Action<T, TValue>));
//var instanceParameter = Expression.Parameter(typeOfT, "instance");
//var valueParameter = Expression.Parameter(typeof(TValue), "value");
//var callExpr = Expression.Call(instanceParameter, setMethod, valueParameter);
//var lambda = Expression.Lambda<Action<T, TValue>>(callExpr, instanceParameter, valueParameter);
//setter = lambda.Compile();
_cache.TryAdd(key, setter);
}
((Action<T, TValue>)setter).Invoke(instance, newValue);
}
}