using System; using System.Collections.Generic; using System.Reflection; using Decal.Adapter.Wrappers; namespace Decal.Adapter; /// /// Base class used to create Decal Plugins /// [CLSCompliant(true)] public abstract class PluginBase : Extension, IViewHandler { private PluginHost myHost; private EventHandler myGraphicsReset; private BindingFlags myBindingFlags; private Dictionary myViews; /// /// Wrapper Object to the Host. /// Similar to IPluginSite /// protected PluginHost Host => myHost; /// /// The Default view /// public ViewWrapper DefaultView => myViews["Default"]; /// /// BindingFlags for internal scanning /// public BindingFlags BindingFlags => myBindingFlags; [CLSCompliant(false)] protected event EventHandler ServerDispatch { add { if (base.Core.EchoFilter != null) { base.Core.EchoFilter.ServerDispatch += value; } } remove { if (base.Core.EchoFilter != null) { base.Core.EchoFilter.ServerDispatch -= value; } } } [CLSCompliant(false)] protected event EventHandler ClientDispatch { add { if (base.Core.EchoFilter != null) { base.Core.EchoFilter.ClientDispatch += value; } } remove { if (base.Core.EchoFilter != null) { base.Core.EchoFilter.ClientDispatch -= value; } } } protected event EventHandler GraphicsReset { add { myGraphicsReset = (EventHandler)Delegate.Combine(myGraphicsReset, value); if (myHost != null) { myHost.Render.DeviceLost += value; } } remove { myGraphicsReset = (EventHandler)Delegate.Remove(myGraphicsReset, value); if (myHost != null) { myHost.Render.DeviceLost -= value; } } } /// /// Default Constructor for the Base class. Should be called by all decendants. /// protected PluginBase() : base(DecalExtensionType.Plugin) { myBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; } /// /// Called by the base class to Wire Up events. /// internal override void Wireup() { if (myGraphicsReset != null) { Host.Render.DeviceLost += myGraphicsReset; } scanBaseEvents(connect: true); myViews = new Dictionary(); PluginHost.LoadViewHandler(this); } /// /// Called by the base class to Unwire events /// internal override void UnWire() { if (myGraphicsReset != null) { Host.Render.DeviceLost -= myGraphicsReset; } scanBaseEvents(connect: false); foreach (ViewWrapper value in myViews.Values) { value.Dispose(); } myViews.Clear(); } /// /// Used for internal wiring up of base-class variables. /// Called by PluginProxy /// /// Host (pluginsite) object internal void SetHost(PluginHost newHost) { myHost = newHost; } private void scanBaseEvents(bool connect) { Type type = GetType(); Type type2 = base.Core.GetType(); if (!Attribute.IsDefined(type, typeof(WireUpBaseEventsAttribute))) { return; } MethodInfo[] methods = type.GetMethods(BindingFlags); foreach (MethodInfo methodInfo in methods) { if (!Attribute.IsDefined(methodInfo, typeof(BaseEventAttribute))) { continue; } Attribute[] customAttributes = Attribute.GetCustomAttributes(methodInfo, typeof(BaseEventAttribute)); for (int j = 0; j < customAttributes.Length; j++) { BaseEventAttribute baseEventAttribute = (BaseEventAttribute)customAttributes[j]; object obj; Type type3; if (baseEventAttribute.FilterName == string.Empty) { obj = this; type3 = type; } else { PropertyInfo property = type2.GetProperty(baseEventAttribute.FilterName, BindingFlags.Instance | BindingFlags.Public); if (property == null) { continue; } obj = property.GetValue(base.Core, null); type3 = obj.GetType(); } EventInfo eventInfo = null; while ((eventInfo = type3.GetEvent(baseEventAttribute.EventName, BindingFlags)) == null && type3 == type) { type3 = type2; obj = base.Core; } if (!(eventInfo == null)) { if (connect) { eventInfo.GetAddMethod(nonPublic: true).Invoke(obj, new object[1] { Delegate.CreateDelegate(eventInfo.EventHandlerType, this, methodInfo.Name) }); } else { eventInfo.GetRemoveMethod(nonPublic: true).Invoke(obj, new object[1] { Delegate.CreateDelegate(eventInfo.EventHandlerType, this, methodInfo.Name) }); } } } } } /// /// Loads a new view into the internal list (should only be called internally) /// /// view name /// resource path public void LoadView(string name, string resource) { myViews.Add(name, Host.LoadViewResource(resource, GetType().Assembly)); } /// /// Retrieves a view from the internal list /// /// view name /// the specified view or null public ViewWrapper GetView(string name) { if (myViews.TryGetValue(name, out var value)) { return value; } return null; } }