using System.Reflection; using System.Collections.Generic; using System; namespace com.bbbirder.injection { public interface IProxyData : IInjection { } public abstract class ProxyData : IProxyData { static readonly BindingFlags bindingFlags = 0 | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly ; // static bool m_IsFixed {get;set;} static Dictionary> s_AllGetters = new(); static Dictionary> s_AllSetters = new(); protected Dictionary getters { get { var type = GetType(); if (!s_AllGetters.TryGetValue(type, out var result)) { result = s_AllGetters[type] = new(); } return result; } } protected Dictionary setters { get { var type = GetType(); if (!s_AllSetters.TryGetValue(type, out var result)) { result = s_AllSetters[type] = new(); } return result; } } public Action OnSetProperty { get; set; } public Action OnGetProperty { get; set; } Func ProxyGet(string name) where C : ProxyData { return o => { // DebugHelper.Log("get " + name); o.OnGetProperty?.Invoke(name); var getter = o.getters[name]; var method = getter as Func; return method.Invoke(o); }; } Action ProxySet(string name) where C : ProxyData { return (o, v) => { var setter = o.setters[name]; var method = setter as Action; method.Invoke(o, v); // DebugHelper.Log("set " + name + "=" + v); o.OnSetProperty?.Invoke(name); }; } /// /// whether this type of data is properly injected and fixed /// /// public bool IsFixed(){ // DebugHelper.Log(m_IsFixed); return FixHelper.IsInjected(GetType()); } public IEnumerable ProvideInjections() { var targetType = this.GetType(); if (targetType.IsAbstract || targetType.IsInterface) yield break; var proxyGet = typeof(ProxyData).GetMethod(nameof(ProxyGet), bindingFlags); var proxySet = typeof(ProxyData).GetMethod(nameof(ProxySet), bindingFlags); var instMethod = default(MethodInfo); var nameArgs = new string[1]; foreach (var property in targetType.GetProperties(bindingFlags)) { var name = property.Name; nameArgs[0] = name; instMethod = proxyGet.MakeGenericMethod(targetType, property.PropertyType); if (property.GetMethod != null) { yield return InjectionInfo.Create( property.GetMethod, instMethod.Invoke(this, nameArgs) as Delegate, f => { // m_IsFixed = true; getters[name] = f; } ); } instMethod = proxySet.MakeGenericMethod(targetType, property.PropertyType); if (property.SetMethod != null) { yield return InjectionInfo.Create( property.SetMethod, instMethod.Invoke(this, nameArgs) as Delegate, f => { // m_IsFixed = true; setters[name] = f; } ); } } } } }