using System; using System.Collections.Generic; using System.Linq; namespace OpenTap { /// Helper class for producing mixin builders. static class MixinFactory { /// Creates mixin builders for a type. public static IEnumerable GetMixinBuilders(ITypeData targetType) { foreach (var factoryType in TypeData.GetDerivedTypes()) { if (factoryType.CanCreateInstance == false) continue; var types = factoryType.GetAttribute()?.Types ?? Array.Empty(); if (!types.Any(targetType.DescendsTo)) continue; var instance = (IMixinBuilder)factoryType.CreateInstance(); instance.Initialize(targetType); yield return instance; } } static readonly TraceSource log = Log.CreateSource("Mixins"); public static MixinMemberData LoadMixin(object target, IMixinBuilder mixin) { try { var mem = mixin.ToDynamicMember(TypeData.GetTypeData(target)); if (mem == null) { if (mixin is IValidatingObject validating && validating.Error is string err && string.IsNullOrEmpty(err) == false) { log.Error($"Unable to load mixin: {err}"); } else { log.Error($"Unable to load mixin: {TypeData.GetTypeData(mixin)?.GetDisplayAttribute()?.Name ?? mixin.ToString()}"); } return null; } DynamicMember.AddDynamicMember(target, mem); mem.SetValue(target, mem.NewInstance()); return mem; } catch (Exception e) { log.Error($"Unable to load mixin: {e.Message}"); log.Debug(e); } return null; } // Unload and dispose mixin member data public static void UnloadMixin(object src2, MixinMemberData remMember) { var member = DynamicMember.GetDynamicMembers(src2).FirstOrDefault(x => remMember.Name == x.Name); //var member = TypeData.GetTypeData(src2).GetMember(remMember.Name); if (member == null) return; DynamicMember.RemoveDynamicMember(src2, member); if (member is MixinMemberData mixin) mixin.Dispose(); } } }