通知服务由通知类型和通知分发类型两部分组成。INotificationType 定义您的通知,并允许您设置名称、权限和消息。当触发通知事件时,INotificationDistributionType 负责通过特定媒介发送通知。开箱即用的 Limyee 电商平台提供两种分发类型,电子邮件、SMS 和 Socket(冒泡提示)分发类型。
为什么要创建通知类型?
当您想要通知平台会员特定事件时,新的通知类型非常有用,这些事件可能是使用核心功能发生的事件,也可能是在平台中添加的新功能发生的事件。
为什么要创建通知分发类型?
除了通过电子邮件、SMS 和 Socket(冒泡提示)发送通知外,新的分发类型还可以通过其他媒介发送通知。例如,您可以使用文本消息平台传递分发通知。定义分发类型超出了本文档的讨论范围。
创建 INotificationType
要添加通过 Limyee 电商平台发送通知的支持,必须实现 INotificationType 插件。INotificationType 接口扩展了 IPlugin,插件必须引用 Limyee.Components.dll、Limyee.Api 和 Limyee.Core 的程序集。
创建 NotificationType 插件时,请使用事件处理程序来创建通知。例如,如果用户对内容进行评论,则可以在插件的 Initialize 方法中为事件创建事件处理程序。然后可以使用控制器发送通知。
private void CommentEvents_AfterCreate(CommentAfterCreateEventArgs e) { if (e == null || e.Content == null || e.User == null || !e.IsApproved || !e.Content.CreatedByUserId.HasValue || e.CommentTypeId.GetValueOrDefault(Guid.Empty) != Guid.Empty) { return; } var comment = Apis.Get<IComments>().Get(e.CommentId); if (comment != null && comment.IsApproved) { AddNotifications(e.Content.ContentId, e.Content.ContentTypeId, e.CommentId, e.Content.CreatedByUserId.Value, e.UserId); } }
当调用 SetController 时,插件的通知控制器实例将传递到 INotificationType。这是通知插件的关键部分。如果未将此处看到的专用 INotification 控制器赋值给 _notificationController,则无法发送通知。
public void SetController(INotificationController controller) { _notificationController = controller; }
在 AddNotifications 方法中,需要使用 INotificationController。调用 CreateUpdate 方法时,将发生两种处理情况:如果存在与 ContentId 和 ContentTypeId 匹配的通知,它将相应地修改通知、如果通知不存在,它将创建一个通知。
或者,INotificationController 中还有一个 Delete 方法,如果实现了 BeforeDelete 事件处理程序,则可以使用该方法。
如果在呈现消息时需要传递其他信息,也可以添加扩展设置。在此示例中,我们定义了稍后在 GetTargetUrl 方法中使用的内容 ID 和类型,并将评论 ID 另存为 ExtendedAttribute,以便以后可以在 GetMessage 中使用。
private void AddNotifications(Guid contentId, Guid contentTypeId, Guid commentId, int contentAuthor, int actorId) { var comment = Apis.Get<IComments>().Get(commentId); if (comment == null) { return; } var attributes = new List<IExtendedAttribute> { new ExtendedAttribute {Key = "TargetCommentId", Value = comment.CommentId.ToString("N")} }; _notificationController.CreateUpdate(new NotificationCreateUpdateOptions { ContentId = contentId, ContentTypeId = contentTypeId, LastUpdate = DateTime.UtcNow, UserId = contentAuthor, ActorIdToAdd = actorId, ExtendedAttributes = attributes }); }
首先为通知类型选择名称和描述,这与插件名称不同,它将显示在用户的设置页面的“通知”选项卡下。
public string NotificationTypeName { get { return "通知示例"; } } public string NotificationTypeDescription { get { return "发送示例通知"; } }
通知类型 Id 是通知类型的唯一 ID。
public Guid NotificationTypeId { get { return new Guid("73CCB067-42B8-40B5-9AA6-A585FB3E7316"); } }
若要告诉系统是否可以并且应该缓存通知数据,请使用 IsCacheable 属性。另一个缓存属性 VaryCacheByUser 告诉系统是否应根据每个用户缓存通知数据。
public bool IsCacheable { get { return true; } } public bool VaryCacheByUser { get { return true; } }
有必要定义用户是否可以删除通知。此值告诉系统是否允许用户删除通知。在此示例中,只有收件人才允许删除,收件人在通知中由 UserId 定义。
public bool CanDeleteNotification(Guid notificationId, int userId) { var notification = PublicApi.Notifications.Get(notificationId); return notification != null && notification.UserId == userId; }
GetMessage 返回发送给用户的消息的字符串值。在这里,可以访问扩展属性,信息是从 CommentEvents_AfterCreate 中的创建通知传入的。
public string GetMessage(Guid notificationId, string target) { var notification = Apis.Get<INotifications>().Get(notificationId); if (notification == null || notification.ExtendedAttributes == null) { return null; } var commentIdAttribute = notification.ExtendedAttributes.FirstOrDefault(ea => ea.Key == "TargetCommentId"); if (commentIdAttribute == null) { return null; } var commentId = Guid.Parse(commentIdAttribute.Value); var comment = Apis.Get<IComments>().Get(commentId); if (comment == null) { return null; } var user = Apis.Get<IUsers>().Get(new UsersGetOptions { Id = notification.UserId }); if (user == null) { return null; } return string.Format("以下注释由 {0} 添加: \"{1}\"", user.DisplayName, comment.Body()); }
GetTargetUrl 将包含内容所在的 URL,并返回该位置的字符串值。在此示例中,评论包含与其关联的内容 ID 和类型,用户点击通知可返回内容。
public string GetTargetUrl(Guid notificationId) { var notification = Apis.Get<INotifications>().Get(notificationId); return notification != null && notification.Content != null ? notification.Content.Url : null; }
下面是完整示例。
using System; using System.Collections.Generic; using System.Linq; using Limyee.Extensibility; using Limyee.Extensibility.Api.Entities.Version1; using Limyee.Extensibility.Api.Version1; using Limyee.Extensibility.Content.Version1; namespace Samples { public class MyNotifications : INotificationType { private INotificationController _notificationController; #region IPlugin public string Name { get { return "我的通知插件"; } } public string Description { get { return "此插件将演示 INotificationType 插件的工作原理"; } } public void Initialize() { Apis.Get<IComments>().Events.AfterCreate += CommentEvents_AfterCreate; } #endregion #region INotificationType public string NotificationTypeName { get { return "通知示例"; } } public string NotificationTypeDescription { get { return "发送示例通知"; } } public string NotificationTypeCategory { get { return "示例"; } } public Guid NotificationTypeId { get { return new Guid("73CCB067-42B8-40B5-9AA6-A585FB3E7316"); } } public bool IsCacheable { get { return true; } } public bool VaryCacheByUser { get { return true; } } public bool CanDeleteNotification(Guid notificationId, int userId) { var notification = Apis.Get<INotifications>().Get(notificationId); return notification != null && notification.UserId == userId; } public string GetMessage(Guid notificationId, string target) { var notification = Apis.Get<INotifications>().Get(notificationId); if (notification == null || notification.ExtendedAttributes == null) { return null; } var commentIdAttribute = notification.ExtendedAttributes.FirstOrDefault(ea => ea.Key == "TargetCommentId"); if (commentIdAttribute == null) { return null; } var commentId = Guid.Parse(commentIdAttribute.Value); var comment = Apis.Get<IComments>().Get(commentId); if (comment == null) { return null; } var user = Apis.Get<IUsers>().Get(new UsersGetOptions { Id = notification.UserId }); if (user == null) { return null; } return string.Format("以下注释由 {0} 添加: \"{1}\"", user.DisplayName, comment.Body()); } public string GetTargetUrl(Guid notificationId) { var notification = Apis.Get<INotifications>().Get(notificationId); return notification != null && notification.Content != null ? notification.Content.Url : null; } public void SetController(INotificationController controller) { _notificationController = controller; } #endregion private void CommentEvents_AfterCreate(CommentAfterCreateEventArgs e) { if (e == null || e.Content == null || e.User == null || !e.IsApproved || !e.Content.CreatedByUserId.HasValue || e.CommentTypeId.GetValueOrDefault(Guid.Empty) != Guid.Empty) { return; } var comment = Apis.Get<IComments>().Get(e.CommentId); if (comment != null && comment.IsApproved) { AddNotifications(e.Content.ContentId, e.Content.ContentTypeId, e.CommentId, e.Content.CreatedByUserId.Value, e.UserId); } } private void AddNotifications(Guid contentId, Guid contentTypeId, Guid commentId, int contentAuthor, int actorId) { var comment = Apis.Get<IComments>().Get(commentId); if (comment == null) { return; } var attributes = new List<IExtendedAttribute> { new ExtendedAttribute {Key = "TargetCommentId", Value = comment.CommentId.ToString("N")} }; _notificationController.CreateUpdate(new NotificationCreateUpdateOptions { ContentId = contentId, ContentTypeId = contentTypeId, LastUpdate = DateTime.UtcNow, UserId = contentAuthor, ActorIdToAdd = actorId, ExtendedAttributes = attributes }); } } }
在此示例中,创建评论时将显示通知。要启用该插件,请导航到:系统管理 > 通知 > 通知 > 我的通知插件。
创建评论可注意到冒泡通知。这是冒泡通知的示例。