From b3c0aae95129d80f7b6f8983a27c73adcb7b9c19 Mon Sep 17 00:00:00 2001 From: Patrick Simpson Date: Mon, 13 Feb 2017 14:02:37 +0100 Subject: [PATCH] Further event hooking tests --- .../AcaciaZPushPlugin.csproj | 2 + .../AcaciaZPushPlugin/Stubs/IItem.cs | 8 + .../AcaciaZPushPlugin/Stubs/IItemEvents.cs | 44 +++++ .../OutlookWrappers/ItemEventsWrapper.cs | 179 ++++++++++++++++++ .../OutlookWrappers/OutlookItemWrapper.cs | 11 ++ .../AcaciaZPushPlugin/Stubs/Wrappers.cs | 8 +- .../AcaciaZPushPlugin/Utils/MailEvents.cs | 139 ++++++-------- 7 files changed, 307 insertions(+), 84 deletions(-) create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IItemEvents.cs create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ItemEventsWrapper.cs diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj index 1a546d4..746e59c 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj @@ -285,12 +285,14 @@ + + diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IItem.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IItem.cs index 30ed2a0..5846ab6 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IItem.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IItem.cs @@ -34,6 +34,14 @@ namespace Acacia.Stubs string Body { get; set; } string Subject { get; set; } + /// + /// Returns the events for the item. The same object is returned, it does not need to be disposed. + /// + IItemEvents Events + { + get; + } + #endregion #region User properties diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IItemEvents.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IItemEvents.cs new file mode 100644 index 0000000..7628d9c --- /dev/null +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IItemEvents.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using NSOutlook = Microsoft.Office.Interop.Outlook; + +namespace Acacia.Stubs +{ + public interface IItemEvents + { + #region Event handlers + + // TODO: custom delegates + event NSOutlook.ItemEvents_10_AfterWriteEventHandler AfterWrite; + event NSOutlook.ItemEvents_10_AttachmentAddEventHandler AttachmentAdd; + event NSOutlook.ItemEvents_10_AttachmentReadEventHandler AttachmentRead; + event NSOutlook.ItemEvents_10_AttachmentRemoveEventHandler AttachmentRemove; + event NSOutlook.ItemEvents_10_BeforeAttachmentAddEventHandler BeforeAttachmentAdd; + event NSOutlook.ItemEvents_10_BeforeAttachmentPreviewEventHandler BeforeAttachmentPreview; + event NSOutlook.ItemEvents_10_BeforeAttachmentReadEventHandler BeforeAttachmentRead; + event NSOutlook.ItemEvents_10_BeforeAttachmentSaveEventHandler BeforeAttachmentSave; + event NSOutlook.ItemEvents_10_BeforeAttachmentWriteToTempFileEventHandler BeforeAttachmentWriteToTempFile; + event NSOutlook.ItemEvents_10_BeforeAutoSaveEventHandler BeforeAutoSave; + event NSOutlook.ItemEvents_10_BeforeCheckNamesEventHandler BeforeCheckNames; + event NSOutlook.ItemEvents_10_BeforeDeleteEventHandler BeforeDelete; + event NSOutlook.ItemEvents_10_BeforeReadEventHandler BeforeRead; + event NSOutlook.ItemEvents_10_CloseEventHandler Close; + event NSOutlook.ItemEvents_10_CustomActionEventHandler CustomAction; + event NSOutlook.ItemEvents_10_CustomPropertyChangeEventHandler CustomPropertyChange; + event NSOutlook.ItemEvents_10_ForwardEventHandler Forward; + event NSOutlook.ItemEvents_10_OpenEventHandler Open; + event NSOutlook.ItemEvents_10_PropertyChangeEventHandler PropertyChange; + event NSOutlook.ItemEvents_10_ReadEventHandler Read; + event NSOutlook.ItemEvents_10_ReadCompleteEventHandler ReadComplete; + event NSOutlook.ItemEvents_10_ReplyEventHandler Reply; + event NSOutlook.ItemEvents_10_ReplyAllEventHandler ReplyAll; + event NSOutlook.ItemEvents_10_SendEventHandler Send; + event NSOutlook.ItemEvents_10_UnloadEventHandler Unload; + event NSOutlook.ItemEvents_10_WriteEventHandler Write; + + #endregion + } +} diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ItemEventsWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ItemEventsWrapper.cs new file mode 100644 index 0000000..378f125 --- /dev/null +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ItemEventsWrapper.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using NSOutlook = Microsoft.Office.Interop.Outlook; + +namespace Acacia.Stubs.OutlookWrappers +{ + class ItemEventsWrapper : IItemEvents + { + private readonly NSOutlook.ItemEvents_10_Event _item; + + internal ItemEventsWrapper(object item) + { + this._item = (NSOutlook.ItemEvents_10_Event)item; + } + + #region Events + + public event NSOutlook.ItemEvents_10_AfterWriteEventHandler AfterWrite + { + add { _item.AfterWrite += value; } + remove { _item.AfterWrite -= value; } + } + + public event NSOutlook.ItemEvents_10_AttachmentAddEventHandler AttachmentAdd + { + add { _item.AttachmentAdd += value; } + remove { _item.AttachmentAdd -= value; } + } + + public event NSOutlook.ItemEvents_10_AttachmentReadEventHandler AttachmentRead + { + add { _item.AttachmentRead += value; } + remove { _item.AttachmentRead -= value; } + } + + public event NSOutlook.ItemEvents_10_AttachmentRemoveEventHandler AttachmentRemove + { + add { _item.AttachmentRemove += value; } + remove { _item.AttachmentRemove -= value; } + } + + public event NSOutlook.ItemEvents_10_BeforeAttachmentAddEventHandler BeforeAttachmentAdd + { + add { _item.BeforeAttachmentAdd += value; } + remove { _item.BeforeAttachmentAdd -= value; } + } + + public event NSOutlook.ItemEvents_10_BeforeAttachmentPreviewEventHandler BeforeAttachmentPreview + { + add { _item.BeforeAttachmentPreview += value; } + remove { _item.BeforeAttachmentPreview -= value; } + } + + public event NSOutlook.ItemEvents_10_BeforeAttachmentReadEventHandler BeforeAttachmentRead + { + add { _item.BeforeAttachmentRead += value; } + remove { _item.BeforeAttachmentRead -= value; } + } + + public event NSOutlook.ItemEvents_10_BeforeAttachmentSaveEventHandler BeforeAttachmentSave + { + add { _item.BeforeAttachmentSave += value; } + remove { _item.BeforeAttachmentSave -= value; } + } + + public event NSOutlook.ItemEvents_10_BeforeAttachmentWriteToTempFileEventHandler BeforeAttachmentWriteToTempFile + { + add { _item.BeforeAttachmentWriteToTempFile += value; } + remove { _item.BeforeAttachmentWriteToTempFile -= value; } + } + + public event NSOutlook.ItemEvents_10_BeforeAutoSaveEventHandler BeforeAutoSave + { + add { _item.BeforeAutoSave += value; } + remove { _item.BeforeAutoSave -= value; } + } + + public event NSOutlook.ItemEvents_10_BeforeCheckNamesEventHandler BeforeCheckNames + { + add { _item.BeforeCheckNames += value; } + remove { _item.BeforeCheckNames -= value; } + } + + public event NSOutlook.ItemEvents_10_BeforeDeleteEventHandler BeforeDelete + { + add { _item.BeforeDelete += value; } + remove { _item.BeforeDelete -= value; } + } + + public event NSOutlook.ItemEvents_10_BeforeReadEventHandler BeforeRead + { + add { _item.BeforeRead += value; } + remove { _item.BeforeRead -= value; } + } + + public event NSOutlook.ItemEvents_10_CloseEventHandler Close + { + add { _item.Close += value; } + remove { _item.Close -= value; } + } + + public event NSOutlook.ItemEvents_10_CustomActionEventHandler CustomAction + { + add { _item.CustomAction += value; } + remove { _item.CustomAction -= value; } + } + + public event NSOutlook.ItemEvents_10_CustomPropertyChangeEventHandler CustomPropertyChange + { + add { _item.CustomPropertyChange += value; } + remove { _item.CustomPropertyChange -= value; } + } + + public event NSOutlook.ItemEvents_10_ForwardEventHandler Forward + { + add { _item.Forward += value; } + remove { _item.Forward -= value; } + } + + public event NSOutlook.ItemEvents_10_OpenEventHandler Open + { + add { _item.Open += value; } + remove { _item.Open -= value; } + } + + public event NSOutlook.ItemEvents_10_PropertyChangeEventHandler PropertyChange + { + add { _item.PropertyChange += value; } + remove { _item.PropertyChange -= value; } + } + + public event NSOutlook.ItemEvents_10_ReadEventHandler Read + { + add { _item.Read += value; } + remove { _item.Read -= value; } + } + + public event NSOutlook.ItemEvents_10_ReadCompleteEventHandler ReadComplete + { + add { _item.ReadComplete += value; } + remove { _item.ReadComplete -= value; } + } + + public event NSOutlook.ItemEvents_10_ReplyEventHandler Reply + { + add { _item.Reply += value; } + remove { _item.Reply -= value; } + } + + public event NSOutlook.ItemEvents_10_ReplyAllEventHandler ReplyAll + { + add { _item.ReplyAll += value; } + remove { _item.ReplyAll -= value; } + } + + public event NSOutlook.ItemEvents_10_SendEventHandler Send + { + add { _item.Send += value; } + remove { _item.Send -= value; } + } + + public event NSOutlook.ItemEvents_10_UnloadEventHandler Unload + { + add { _item.Unload += value; } + remove { _item.Unload -= value; } + } + + public event NSOutlook.ItemEvents_10_WriteEventHandler Write + { + add { _item.Write += value; } + remove { _item.Write -= value; } + } + + #endregion + } +} diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/OutlookItemWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/OutlookItemWrapper.cs index eb95a3b..61a352a 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/OutlookItemWrapper.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/OutlookItemWrapper.cs @@ -16,6 +16,17 @@ namespace Acacia.Stubs.OutlookWrappers { } + private ItemEventsWrapper _events; + public IItemEvents Events + { + get + { + if (_events == null) + _events = new ItemEventsWrapper(_item); + return _events; + } + } + public Type GetUserProperty(string name) { using (ComRelease com = new ComRelease()) diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/Wrappers.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/Wrappers.cs index cae4834..a30c9a7 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/Wrappers.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/Wrappers.cs @@ -15,10 +15,16 @@ namespace Acacia.Stubs return Mapping.WrapOrDefault(obj); } - public static WrapType Wrap(object o, bool mustRelease = true) + public static WrapType Wrap(this object o, bool mustRelease = true) where WrapType : IBase { return Mapping.Wrap(o, mustRelease); } + + public static WrapType WrapOrDefault(this object o, bool mustRelease = true) + where WrapType : IBase + { + return Mapping.WrapOrDefault(o, mustRelease); + } } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/MailEvents.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/MailEvents.cs index 0a9442f..044562d 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/MailEvents.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/MailEvents.cs @@ -21,7 +21,6 @@ using System.Text; using System.Threading.Tasks; using Acacia.Stubs; using Acacia.Stubs.OutlookWrappers; -using NSOutlook = Microsoft.Office.Interop.Outlook; namespace Acacia.Utils { @@ -47,22 +46,18 @@ namespace Acacia.Utils public event MailResponseEventHandler Respond; public event MailResponseEventHandler Reply; - private void OnReply(NSOutlook.MailItem mail, NSOutlook.MailItem response) + private void OnReply(IMailItem mail, IMailItem response) { // TODO: check release of first item // TODO: release if not sending event try { - if ((Reply != null || Respond != null) && mail != null) + if ((Reply != null || Respond != null) && mail != null && response != null) { - using (IMailItem mailWrapped = Mapping.Wrap(mail, false), - responseWrapped = Mapping.Wrap(response)) - { - if (Reply != null) - Reply(mailWrapped, responseWrapped); - if (Respond != null) - Respond(mailWrapped, responseWrapped); - } + if (Reply != null) + Reply(mail, response); + if (Respond != null) + Respond(mail, response); } } catch (System.Exception e) @@ -72,22 +67,18 @@ namespace Acacia.Utils } public event MailResponseEventHandler ReplyAll; - private void OnReplyAll(NSOutlook.MailItem mail, NSOutlook.MailItem response) + private void OnReplyAll(IMailItem mail, IMailItem response) { // TODO: check release of first item // TODO: release if not sending event try { - if ((ReplyAll != null || Respond != null) && mail != null) + if ((ReplyAll != null || Respond != null) && mail != null && response != null) { - using (IMailItem mailWrapped = Mapping.Wrap(mail, false), - responseWrapped = Mapping.Wrap(response)) - { - if (ReplyAll != null) - ReplyAll(mailWrapped, responseWrapped); - if (Respond != null) - Respond(mailWrapped, responseWrapped); - } + if (ReplyAll != null) + ReplyAll(mail, response); + if (Respond != null) + Respond(mail, response); } } catch (System.Exception e) @@ -97,22 +88,18 @@ namespace Acacia.Utils } public event MailResponseEventHandler Forward; - private void OnForward(NSOutlook.MailItem mail, NSOutlook.MailItem response) + private void OnForward(IMailItem mail, IMailItem response) { // TODO: check release of first item // TODO: release if not sending event try { - if ((Forward != null || Respond != null) && mail != null) + if ((Forward != null || Respond != null) && mail != null && response != null) { - using (IMailItem mailWrapped = Mapping.Wrap(mail, false), - responseWrapped = Mapping.Wrap(response)) - { - if (Forward != null) - Forward(mailWrapped, responseWrapped); - if (Respond != null) - Respond(mailWrapped, responseWrapped); - } + if (Forward != null) + Forward(mail, response); + if (Respond != null) + Respond(mail, response); } } catch (System.Exception e) @@ -122,18 +109,13 @@ namespace Acacia.Utils } public event MailEventHandler Read; - private void OnRead(NSOutlook.MailItem mail) + private void OnRead(IMailItem mail) { - // TODO: check release of first item - // TODO: release if not sending event try { if (Read != null && mail != null) { - using (IMailItem wrapped = Mapping.Wrap(mail, false)) - { - Read(wrapped); - } + Read(mail); } } catch (System.Exception e) @@ -143,17 +125,13 @@ namespace Acacia.Utils } public event CancellableItemEventHandler BeforeDelete; - private void OnBeforeDelete(object item, ref bool cancel) + private void OnBeforeDelete(IItem item, ref bool cancel) { try { if (BeforeDelete != null && item != null) { - using (IItem wrapped = Mapping.Wrap(item, false)) - { - if (wrapped != null) - BeforeDelete(wrapped, ref cancel); - } + BeforeDelete(item, ref cancel); } } catch(System.Exception e) @@ -164,17 +142,13 @@ namespace Acacia.Utils // TODO: should this be CancellableMailItemEventHandler? public event CancellableItemEventHandler Write; - private void OnWrite(object item, ref bool cancel) + private void OnWrite(IItem item, ref bool cancel) { try { if (Write != null && item != null) { - using (IItem wrapped = Mapping.Wrap(item, false)) - { - if (wrapped != null) - Write(wrapped, ref cancel); - } + Write(item, ref cancel); } } catch (System.Exception e) @@ -216,104 +190,103 @@ namespace Acacia.Utils private void OnItemLoad(object item) { - using (IItem wrapped = Wrappers.Wrap(item)) + IItem wrapped = Wrappers.Wrap(item); + // TODO: check type + if (wrapped != null) { + new MailEventHooker(wrapped, this); } - - /* - NSOutlook.ItemEvents_10_Event hasEvents = item as NSOutlook.ItemEvents_10_Event; - if (hasEvents != null) - { - new MailEventHooker(hasEvents, this); - }*/ } - private class MailEventHooker : ComWrapper + private class MailEventHooker : DisposableWrapper { + private IItem _item; private readonly MailEvents _events; // TODO: remove id and debug logging private int _id; private static int nextId; - public MailEventHooker(NSOutlook.ItemEvents_10_Event itemEvents, MailEvents events) : base(itemEvents) + public MailEventHooker(IItem item, MailEvents events) { + this._item = item; this._id = ++nextId; this._events = events; HookEvents(true); } - ~MailEventHooker() + /*~MailEventHooker() { - } + */ protected override void DoRelease() { Logger.Instance.Debug(this, "DoRelease: {0}", _id); // TODO: It looks like release _itemEvents is not only not needed, but causes exceptions. // If that is really the case, this doesn't need to be a ComWrapper + _item.Dispose(); } private void HookEvents(bool add) { if (add) { - _item.BeforeDelete += HandleBeforeDelete; - _item.Forward += HandleForward; - _item.Read += HandleRead; - _item.Reply += HandleReply; - _item.ReplyAll += HandleReplyAll; - _item.Unload += HandleUnload; - _item.Write += HandleWrite; + _item.Events.BeforeDelete += HandleBeforeDelete; + _item.Events.Forward += HandleForward; + _item.Events.Read += HandleRead; + _item.Events.Reply += HandleReply; + _item.Events.ReplyAll += HandleReplyAll; + _item.Events.Unload += HandleUnload; + _item.Events.Write += HandleWrite; } else { - _item.BeforeDelete -= HandleBeforeDelete; - _item.Forward -= HandleForward; - _item.Read -= HandleRead; - _item.Reply -= HandleReply; - _item.ReplyAll -= HandleReplyAll; - _item.Unload -= HandleUnload; - _item.Write -= HandleWrite; + _item.Events.BeforeDelete -= HandleBeforeDelete; + _item.Events.Forward -= HandleForward; + _item.Events.Read -= HandleRead; + _item.Events.Reply -= HandleReply; + _item.Events.ReplyAll -= HandleReplyAll; + _item.Events.Unload -= HandleUnload; + _item.Events.Write -= HandleWrite; } } private void HandleBeforeDelete(object item, ref bool cancel) { Logger.Instance.Debug(this, "HandleBeforeDelete: {0}", _id); - _events.OnBeforeDelete(item, ref cancel); + _events.OnBeforeDelete(item.WrapOrDefault(), ref cancel); } private void HandleForward(object response, ref bool cancel) { Logger.Instance.Debug(this, "HandleForward: {0}", _id); - _events.OnForward(_item as NSOutlook.MailItem, response as NSOutlook.MailItem); + _events.OnForward(_item as IMailItem, response.WrapOrDefault()); } private void HandleRead() { Logger.Instance.Debug(this, "HandleRead: {0}", _id); - _events.OnRead(_item as NSOutlook.MailItem); + _events.OnRead(_item as IMailItem); } private void HandleReply(object response, ref bool cancel) { Logger.Instance.Debug(this, "HandleReply: {0}", _id); - _events.OnReply(_item as NSOutlook.MailItem, response as NSOutlook.MailItem); + _events.OnReply(_item as IMailItem, response.WrapOrDefault()); } private void HandleReplyAll(object response, ref bool cancel) { Logger.Instance.Debug(this, "HandleReplyAll: {0}", _id); - _events.OnReplyAll(_item as NSOutlook.MailItem, response as NSOutlook.MailItem); + _events.OnReplyAll(_item as IMailItem, response.WrapOrDefault()); } private void HandleUnload() { Logger.Instance.Debug(this, "HandleUnload: {0}", _id); // All events must be unhooked on unload, otherwise a resource leak is created. - //HookEvents(false); - //Dispose(); + HookEvents(false); + Dispose(); } private void HandleWrite(ref bool cancel)