using System.Collections.Concurrent; using System.Collections.Frozen; using System.Reflection; using AyCode.Services.SignalRs; namespace AyCode.Models.Server.DynamicMethods; public class AcDynamicMethodCallModel where TAttribute : TagAttribute { /// /// Statikus cache a típusok metódus metaadataihoz - a reflection csak egyszer fut le típusonként. /// Key: Instance típus -> Value: immutable frozen dictionary a metódusokkal messageTag szerint /// private static readonly ConcurrentDictionary>> _typeMethodCache = new(); public object InstanceObject { get; init; } /// /// Immutable dictionary a metódusokkal messageTag szerint. Csak olvasásra használatos. /// public FrozenDictionary> MethodsByMessageTag { get; init; } public AcDynamicMethodCallModel(Type instanceObjectType) : this(instanceObjectType, null!) { } public AcDynamicMethodCallModel(Type instanceObjectType, params object[] constructorParams) : this(Activator.CreateInstance(instanceObjectType, constructorParams)!) { } public AcDynamicMethodCallModel(object instanceObject) { InstanceObject = instanceObject; MethodsByMessageTag = GetOrCreateMethodCache(instanceObject.GetType()); } /// /// Visszaadja a cache-elt metódus metaadatokat, vagy létrehozza őket ha még nincsenek. /// A reflection csak egyszer fut le típusonként. /// private static FrozenDictionary> GetOrCreateMethodCache(Type instanceType) { return _typeMethodCache.GetOrAdd(instanceType, type => { var methods = new Dictionary>(); foreach (var methodInfo in type.GetMethods()) { if (methodInfo.GetCustomAttribute(typeof(TAttribute)) is not TAttribute attribute) continue; if (methods.ContainsKey(attribute.MessageTag)) throw new Exception($"Multiple SignaRMessageTag! messageTag: {attribute.MessageTag}; methodName: {methodInfo.Name}"); methods[attribute.MessageTag] = new AcMethodInfoModel(attribute, methodInfo!); } return methods.ToFrozenDictionary(); }); } }