using System; using System.Collections.Concurrent; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Raindrops.SharedTests")] namespace Raindrops.Shared.InvokeST { public class Accessor { internal ConcurrentDictionary _dic; public Accessor(object target) : this(target, target?.GetType() ?? throw new ArgumentNullException(nameof(target))) { } public Accessor(object target, Type elementType) { Target = target; ElementType = elementType; _dic = AccessorHelper.s_map.GetOrAdd(elementType, (type) => new ConcurrentDictionary()); } public object Target { get; } public Type ElementType { get; } public object this[string member] { get { GetHandler get = AccessorHelper.GetGetHandler(_dic, ElementType, member) ?? throw new ArgumentException(nameof(member)); return get(Target); } set { SetHandler set = AccessorHelper.GetSetHandler(_dic, ElementType, member) ?? throw new ArgumentException(nameof(member)); set(Target, value); } } public T GetValue(string member) { return TryGetValue(member,out T value) ? value : throw new ArgumentException(nameof(member)); } public void SetValue(string member,T value) { if (!TrySetValue(member, value)) throw new ArgumentException(nameof(member)); } public bool TryGetValue(string member,out T value) { GetHandler get = AccessorHelper.GetGetHandler(_dic, ElementType, member); if (get != null) { value = get(Target); return true; } value = default; return false; } public bool TrySetValue(string member,T value) { SetHandler set = AccessorHelper.GetSetHandler(_dic, ElementType, member); if (set != null) { set(Target, value); return true; } return false; } } }