1. 目录

1.1 高级插件开发概述

nopCommerce插件系统支持高级自定义和扩展,允许开发者深度集成和扩展核心功能。高级插件开发涉及创建新实体、服务、页面和扩展现有功能)

1.1.1 高级插件开发原理

  • 松耦合设计:避免直接依赖核心代- *可扩展性:设计时考虑未来扩展需- *兼容:确保插件在不同nopCommerce版本间兼容性- 性能优化:注意插件对系统性能的影

1.2 在插件中创建新实现

1.2.1 实体设计与创)

using Nop.Core.Domain.Common;
using System;

namespace Nop.Plugin.Custom.MyPlugin.Domain
{
    /// <summary>
    /// 示例自定义实现    /// </summary>
    public class MyEntity : BaseEntity
    {
        /// <summary>
        /// 获取或设置实体名称        /// </summary>
        public string Name { get; set; }
        
        /// <summary>
        /// 获取或设置描)        /// </summary>
        public string Description { get; set; }
        
        /// <summary>
        /// 获取或设置创建日)        /// </summary>
        public DateTime CreatedOnUtc { get; set; }
        
        /// <summary>
        /// 获取或设置更新日)        /// </summary>
        public DateTime UpdatedOnUtc { get; set; }
    }
}

1.2.2 配置实体映射

using LinqToDB.Mapping;
using Nop.Data.Mapping;
using Nop.Plugin.Custom.MyPlugin.Domain;

namespace Nop.Plugin.Custom.MyPlugin.Data
{
    /// <summary>
    /// 实体映射配置
    /// </summary>
    public partial class MyEntityMap : NopEntityTypeConfiguration<MyEntity>
    {
        /// <summary>
        /// 配置映射
        /// </summary>
        public override void Configure(EntityMappingBuilder<MyEntity> builder)
        {
            builder.HasTableName("MyPlugin_MyEntity");
            
            builder.Property(entity => entity.Name).HasColumnName("Name").IsRequired().HasMaxLength(255);
            builder.Property(entity => entity.Description).HasColumnName("Description").IsNullable().HasMaxLength(1000);
            builder.Property(entity => entity.CreatedOnUtc).HasColumnName("CreatedOnUtc");
            builder.Property(entity => entity.UpdatedOnUtc).HasColumnName("UpdatedOnUtc");
        }
    }
}

1.2.3 更新数据库架构

using FluentMigrator;
using Nop.Data.Migrations;

namespace Nop.Plugin.Custom.MyPlugin.Data
{
    [NopMigration("202401011200", "MyPlugin: Add MyEntity table")]
    public class AddMyEntityTable : AutoReversingMigration
    {
        public override void Up()
        {
            Create.Table("MyPlugin_MyEntity")
                .WithColumn("Id").AsInt32().PrimaryKey().Identity()
                .WithColumn("Name").AsString(255).NotNullable()
                .WithColumn("Description").AsString(1000).Nullable()
                .WithColumn("CreatedOnUtc").AsDateTime().NotNullable()
                .WithColumn("UpdatedOnUtc").AsDateTime().NotNullable();
        }
    }
}

1.3 在插件中添加CRUD服务

1.3.1 服务接口设计

using System.Collections.Generic;
using Nop.Core.Domain.Common;
using Nop.Plugin.Custom.MyPlugin.Domain;

namespace Nop.Plugin.Custom.MyPlugin.Services
{
    /// <summary>
    /// MyEntity服务接口
    /// </summary>
    public interface IMyEntityService
    {
        /// <summary>
        /// 获取所有MyEntity实体
        /// </summary>
        /// <returns>MyEntity实体列表</returns>
        IList<MyEntity> GetAllMyEntities();
        
        /// <summary>
        /// 根据ID获取MyEntity
        /// </summary>
        /// <param name="myEntityId">MyEntity ID</param>
        /// <returns>MyEntity实体</returns>
        MyEntity GetMyEntityById(int myEntityId);
        
        /// <summary>
        /// 插入MyEntity
        /// </summary>
        /// <param name="myEntity">MyEntity实体</param>
        void InsertMyEntity(MyEntity myEntity);
        
        /// <summary>
        /// 更新MyEntity
        /// </summary>
        /// <param name="myEntity">MyEntity实体</param>
        void UpdateMyEntity(MyEntity myEntity);
        
        /// <summary>
        /// 删除MyEntity
        /// </summary>
        /// <param name="myEntity">MyEntity实体</param>
        void DeleteMyEntity(MyEntity myEntity);
    }
}

1.3.2 服务实现

using System.Collections.Generic;
using System.Linq;
using Nop.Core.Data;
using Nop.Plugin.Custom.MyPlugin.Domain;

namespace Nop.Plugin.Custom.MyPlugin.Services
{
    /// <summary>
    /// MyEntity服务实现
    /// </summary>
    public class MyEntityService : IMyEntityService
    {
        private readonly IRepository<MyEntity> _myEntityRepository;
        
        /// <summary>
        /// 构造函)        /// </summary>
        /// <param name="myEntityRepository">MyEntity仓储</param>
        public MyEntityService(IRepository<MyEntity> myEntityRepository)
        {
            _myEntityRepository = myEntityRepository;
        }
        
        /// <summary>
        /// 获取所有MyEntity实体
        /// </summary>
        /// <returns>MyEntity实体列表</returns>
        public IList<MyEntity> GetAllMyEntities()
        {
            return _myEntityRepository.Table.ToList();
        }
        
        /// <summary>
        /// 根据ID获取MyEntity
        /// </summary>
        /// <param name="myEntityId">MyEntity ID</param>
        /// <returns>MyEntity实体</returns>
        public MyEntity GetMyEntityById(int myEntityId)
        {
            return _myEntityRepository.GetById(myEntityId);
        }
        
        /// <summary>
        /// 插入MyEntity
        /// </summary>
        /// <param name="myEntity">MyEntity实体</param>
        public void InsertMyEntity(MyEntity myEntity)
        {
            _myEntityRepository.Insert(myEntity);
        }
        
        /// <summary>
        /// 更新MyEntity
        /// </summary>
        /// <param name="myEntity">MyEntity实体</param>
        public void UpdateMyEntity(MyEntity myEntity)
        {
            _myEntityRepository.Update(myEntity);
        }
        
        /// <summary>
        /// 删除MyEntity
        /// </summary>
        /// <param name="myEntity">MyEntity实体</param>
        public void DeleteMyEntity(MyEntity myEntity)
        {
            _myEntityRepository.Delete(myEntity);
        }
    }
}

1.3.3 服务注册

using Nop.Core.Configuration;
using Nop.Core.Infrastructure;
using Nop.Plugin.Custom.MyPlugin.Services;

namespace Nop.Plugin.Custom.MyPlugin.Infrastructure
{
    /// <summary>
    /// 依赖注册
    /// </summary>
    public class DependencyRegistrar : IDependencyRegistrar
    {
        /// <summary>
        /// 注册依赖
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <param name="typeFinder">类型查找)/param>
        /// <param name="appSettings">应用设置</param>
        public void Register(IServiceCollection services, ITypeFinder typeFinder, AppSettings appSettings)
        {
            // 注册服务
            services.AddScoped<IMyEntityService, MyEntityService>();
        }
        
        /// <summary>
        /// 注册顺序
        /// </summary>
        public int Order => 1;
    }
}

1.4 在插件中添加Tag Helper

1.4.1 创建Tag Helper)

using Microsoft.AspNetCore.Razor.TagHelpers;
using Nop.Services.Configuration;

namespace Nop.Plugin.Custom.MyPlugin.TagHelpers
{
    /// <summary>
    /// MyEntity Tag Helper
    /// </summary>
    [HtmlTargetElement("nop-my-entity", Attributes = MyEntityIdAttributeName, TagStructure = TagStructure.WithoutEndTag)]
    public class MyEntityTagHelper : TagHelper
    {
        private const string MyEntityIdAttributeName = "asp-my-entity-id";
        
        private readonly IMyEntityService _myEntityService;
        
        [HtmlAttributeName(MyEntityIdAttributeName)]
        public int MyEntityId { get; set; }
        
        /// <summary>
        /// 构造函)        /// </summary>
        /// <param name="myEntityService">MyEntity服务</param>
        public MyEntityTagHelper(IMyEntityService myEntityService)
        {
            _myEntityService = myEntityService;
        }
        
        /// <summary>
        /// 处理Tag Helper
        /// </summary>
        /// <param name="context">Tag Helper上下)/param>
        /// <param name="output">Tag Helper输出</param>
        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            var myEntity = _myEntityService.GetMyEntityById(MyEntityId);
            
            if (myEntity != null)
            {
                output.TagName = "div";
                output.Attributes.SetAttribute("class", "my-entity");
                output.Content.SetContent($"<h3>{myEntity.Name}</h3><p>{myEntity.Description}</p>");
            }
            else
            {
                output.SuppressOutput();
            }
        }
    }
}

1.4.2 注册Tag Helper

在插件项目中创建_ViewImports.cshtml文件)

@addTagHelper *, Nop.Plugin.Custom.MyPlugin

1.5 在插件中添加公共商店页面

1.5.1 创建控制)

using Microsoft.AspNetCore.Mvc;
using Nop.Web.Framework.Controllers;
using Nop.Plugin.Custom.MyPlugin.Services;

namespace Nop.Plugin.Custom.MyPlugin.Controllers
{
    /// <summary>
    /// 公共商店控制)    /// </summary>
    public class MyPluginPublicController : BasePluginController
    {
        private readonly IMyEntityService _myEntityService;
        
        public MyPluginPublicController(IMyEntityService myEntityService)
        {
            _myEntityService = myEntityService;
        }
        
        /// <summary>
        /// 列表页面
        /// </summary>
        public IActionResult List()
        {
            var model = new MyEntityListModel
            {
                MyEntities = _myEntityService.GetAllMyEntities()
                    .Select(e => new MyEntityModel
                    {
                        Id = e.Id,
                        Name = e.Name,
                        Description = e.Description
                    })
                    .ToList()
            };
            
            return View("~/Plugins/Custom.MyPlugin/Views/List.cshtml", model);
        }
        
        /// <summary>
        /// 详情页面
        /// </summary>
        /// <param name="id">MyEntity ID</param>
        public IActionResult Detail(int id)
        {
            var myEntity = _myEntityService.GetMyEntityById(id);
            
            if (myEntity == null)
                return NotFound();
            
            var model = new MyEntityModel
            {
                Id = myEntity.Id,
                Name = myEntity.Name,
                Description = myEntity.Description
            };
            
            return View("~/Plugins/Custom.MyPlugin/Views/Detail.cshtml", model);
        }
    }
}

1.5.2 添加路由

RouteProvider.cs中配置路由:

using Nop.Web.Framework.Mvc.Routing;

namespace Nop.Plugin.Custom.MyPlugin.Infrastructure
{
    public partial class RouteProvider : IRouteProvider
    {
        public void RegisterRoutes(IRouteBuilder routeBuilder)
        {
            // 列表页面路由
            routeBuilder.MapRoute("Plugin.Custom.MyPlugin.List", "my-plugin/list",
                new { controller = "MyPluginPublic", action = "List", area = "" });
                
            // 详情页面路由
            routeBuilder.MapRoute("Plugin.Custom.MyPlugin.Detail", "my-plugin/detail/{id:int}",
                new { controller = "MyPluginPublic", action = "Detail", area = "" },
                new { id = @"\d+" });
        }
        
        public int Priority => 0;
    }
}

1.6 订阅事件(添加客户导航菜单)

1.6.1 创建事件消费)

using Nop.Events;
using Nop.Services.Events;
using Nop.Web.Framework.Events;
using Nop.Web.Framework.Models.Topics;

namespace Nop.Plugin.Custom.MyPlugin.Events
{
    /// <summary>
    /// 事件消费)    /// </summary>
    public class EventConsumer : IConsumer<ModelReceivedEvent<CustomerNavigationModel>>
    {
        /// <summary>
        /// 处理事件
        /// </summary>
        /// <param name="eventMessage">事件消息</param>
        public void HandleEvent(ModelReceivedEvent<CustomerNavigationModel> eventMessage)
        {
            // 添加新菜单项到客户导航菜)            eventMessage.Model.Items.Add(new CustomerNavigationItemModel
            {
                RouteName = "Plugin.Custom.MyPlugin.CustomerMenuItem",
                Title = "My Plugin",
                Visible = true,
                Position = 100
            });
        }
    }
}

1.7 在公共商店中显示小部署

1.7.1 创建小部件类

using Microsoft.AspNetCore.Mvc;
using Nop.Services.Cms;
using Nop.Web.Framework.Components;

namespace Nop.Plugin.Custom.MyPlugin.Widgets
{
    /// <summary>
    /// 小部署    /// </summary>
    [ViewComponent(Name = "WidgetsMyPlugin")]
    public class WidgetsMyPluginViewComponent : NopViewComponent
    {
        private readonly IMyEntityService _myEntityService;
        
        public WidgetsMyPluginViewComponent(IMyEntityService myEntityService)
        {
            _myEntityService = myEntityService;
        }
        
        /// <summary>
        /// 调用小部署        /// </summary>
        /// <param name="viewComponentArguments">参数</param>
        /// <returns>视图结果</returns>
        public IViewComponentResult Invoke(dynamic viewComponentArguments)
        {
            var model = new WidgetMyPluginModel
            {
                MyEntities = _myEntityService.GetAllMyEntities().Take(3).ToList()
            };
            
            return View("~/Plugins/Custom.MyPlugin/Views/Widgets/WidgetsMyPlugin.cshtml", model);
        }
    }
}

1.7.2 小部件注)

using Nop.Services.Cms;
using Nop.Services.Configuration;
using Nop.Services.Localization;
using Nop.Web.Framework.Menu;

namespace Nop.Plugin.Custom.MyPlugin
{
    /// <summary>
    /// 插件
    /// </summary>
    public class MyPlugin : BasePlugin, IWidgetPlugin
    {
        // 其他代码
        
        /// <summary>
        /// 获取小部署zones
        /// </summary>
        /// <returns>小部署zones</returns>
        public Task<IList<string>> GetWidgetZonesAsync()
        {
            return Task.FromResult<IList<string>>(new List<string> { "home_page_top" });
        }
        
        /// <summary>
        /// 获取小部件视图组件名称        /// </summary>
        /// <param name="widgetZone">小部署zone</param>
        /// <returns>视图组件名称</returns>
        public Type GetWidgetViewComponent(string widgetZone)
        {
            return typeof(WidgetsMyPluginViewComponent);
        }
    }
}

1.8 在插件中添加新权)

1.8.1 定义权限常量

namespace Nop.Plugin.Custom.MyPlugin
{
    /// <summary>
    /// 权限常量
    /// </summary>
    public static class MyPluginPermissions
    {
        /// <summary>
        /// 管理MyEntity
        /// </summary>
        public const string ManageMyEntities = "MyPlugin.ManageMyEntities";
    }
}

1.8.2 注册权限

using Nop.Services.Security;

namespace Nop.Plugin.Custom.MyPlugin.Infrastructure
{
    /// <summary>
    /// 权限提提供商    /// </summary>
    public class PermissionProvider : IPermissionProvider
    {
        /// <summary>
        /// 获取权限
        /// </summary>
        /// <returns>权限列表</returns>
        public IEnumerable<PermissionRecord> GetPermissions()
        {
            return new[]
            {
                new PermissionRecord {
                    Name = "管理MyEntity",
                    SystemName = MyPluginPermissions.ManageMyEntities,
                    Category = "My Plugin"
                }
            };
        }
        
        /// <summary>
        /// 获取默认权限
        /// </summary>
        /// <returns>默认权限</returns>
        public IEnumerable<DefaultPermissionRecord> GetDefaultPermissions()
        {
            return new[]
            {
                new DefaultPermissionRecord {
                    CustomerRoleSystemName = NopCustomerDefaults.AdministratorsRoleName,
                    PermissionSystemName = MyPluginPermissions.ManageMyEntities
                }
            };
        }
    }
}

1.8.3 使用权限

// 检查权)if (!await _permissionService.AuthorizeAsync(MyPluginPermissions.ManageMyEntities))
    return AccessDeniedView();

1.9 从插件发送电子邮)

1.9.1 发送电子邮件示)

using Nop.Services.Messages;
using Nop.Services.Stores;

namespace Nop.Plugin.Custom.MyPlugin.Services
{
    public class MyEmailService
    {
        private readonly IEmailSender _emailSender;
        private readonly IStoreContext _storeContext;
        
        public MyEmailService(IEmailSender emailSender, IStoreContext storeContext)
        {
            _emailSender = emailSender;
            _storeContext = storeContext;
        }
        
        /// <summary>
        /// 发送自定义邮件
        /// </summary>
        public async Task SendCustomEmailAsync(string email, string subject, string message)
        {
            await _emailSender.SendEmailAsync(
                email: email,
                subject: subject,
                body: message,
                htmlBody: true,
                storeId: _storeContext.CurrentStore.Id
            );
        }
    }
}

1.9.2 覆盖核心方法

// 通过依赖注入替换核心服务实现
public void Register(IServiceCollection services, ITypeFinder typeFinder, AppSettings appSettings)
{
    // 替换核心服务实现
    services.AddScoped<ICoreService, MyCoreServiceOverride>();
}

1.10 在插件中添加管理区域页面

1.10.1 创建管理控制)

using Microsoft.AspNetCore.Mvc;
using Nop.Web.Framework.Controllers.Admin;
using Nop.Web.Framework.Mvc.Filters;
using Nop.Plugin.Custom.MyPlugin.Services;
using Nop.Plugin.Custom.MyPlugin.Models;

namespace Nop.Plugin.Custom.MyPlugin.Controllers
{
    [Area(AreaNames.Admin)]
    [AuthorizeAdmin]
    [AutoValidateAntiforgeryToken]
    public class MyPluginAdminController : BaseAdminController
    {
        private readonly IMyEntityService _myEntityService;
        private readonly IPermissionService _permissionService;
        
        public MyPluginAdminController(IMyEntityService myEntityService, IPermissionService permissionService)
        {
            _myEntityService = myEntityService;
            _permissionService = permissionService;
        }
        
        public IActionResult List()
        {
            if (!_permissionService.Authorize(MyPluginPermissions.ManageMyEntities))
                return AccessDeniedView();
                
            var model = new MyEntityListModel
            {
                Items = _myEntityService.GetAllMyEntities()
                    .Select(e => new MyEntityModel
                    {
                        Id = e.Id,
                        Name = e.Name,
                        Description = e.Description
                    })
                    .ToList()
            };
            
            return View("~/Plugins/Custom.MyPlugin/Views/Admin/List.cshtml", model);
        }
        
        // 其他CRUD操作方法...
    }
}

1.10.2 添加管理菜单

using Nop.Services.Localization;
using Nop.Web.Framework.Menu;

namespace Nop.Plugin.Custom.MyPlugin.Infrastructure
{
    public class AdminMenuPlugin : INopMenuPlugin
    {
        private readonly ILocalizationService _localizationService;
        private readonly IPermissionService _permissionService;
        
        public AdminMenuPlugin(ILocalizationService localizationService, IPermissionService permissionService)
        {
            _localizationService = localizationService;
            _permissionService = permissionService;
        }
        
        public async Task ManageSiteMapAsync(SiteMapNode rootNode)
        {
            if (!await _permissionService.AuthorizeAsync(MyPluginPermissions.ManageMyEntities))
                return;
                
            var menuItem = new SiteMapNode
            {
                SystemName = "MyPlugin.Menu",
                Title = await _localizationService.GetLocalizedAsync("MyPlugin.Menu.Title"),
                ControllerName = "MyPluginAdmin",
                ActionName = "List",
                IconClass = "fa fa-cube",
                Visible = true,
                RouteValues = new RouteValueDictionary { { "area", AreaNames.Admin } }
            };
            
            rootNode.ChildNodes.Add(menuItem);
        }
        
        public int Priority => 1000;
    }
}

1.11 通过插件更新现有核心实体

1.11.1 使用扩展属性

using Nop.Core.Domain.Common;
using Nop.Plugin.Custom.MyPlugin.Domain;

namespace Nop.Plugin.Custom.MyPlugin.Extensions
{
    public static class CustomerExtensions
    {
        /// <summary>
        /// 获取MyEntity ID
        /// </summary>
        public static int GetMyEntityId(this Customer customer)
        {
            return customer.GetAttribute<int>("MyEntityId");
        }
        
        /// <summary>
        /// 设置MyEntity ID
        /// </summary>
        public static void SetMyEntityId(this Customer customer, int myEntityId)
        {
            customer.SetAttribute("MyEntityId", myEntityId);
        }
    }
}

1.11.2 使用自定义字)

// 在迁移中添加自定义字)public override void Up()
{
    // 注意:不推荐直接修改核心表,建议使用扩展属性    // 以下仅为示例
    Alter.Table("Customer")
        .AddColumn("MyCustomField").AsString(255).Nullable();
}

1.12 在插件中添加新字段到现有管理页面

1.12.1 使用模型事件

using Nop.Events;
using Nop.Services.Events;
using Nop.Web.Areas.Admin.Models.Customers;

namespace Nop.Plugin.Custom.MyPlugin.Events
{
    public class ModelEventConsumer : IConsumer<ModelReceivedEvent<CustomerModel>>,
                                       IConsumer<ModelPreparedEvent<CustomerModel>>
    {
        private readonly IMyEntityService _myEntityService;
        private readonly ICustomerService _customerService;
        
        public ModelEventConsumer(IMyEntityService myEntityService, ICustomerService customerService)
        {
            _myEntityService = myEntityService;
            _customerService = customerService;
        }
        
        // 模型准备份        public void HandleEvent(ModelPreparedEvent<CustomerModel> eventMessage)
        {
            var customer = _customerService.GetCustomerById(eventMessage.Model.Id);
            if (customer != null)
            {
                // 添加自定义字段值到模型
                eventMessage.Model.CustomProperties["MyEntityId"] = customer.GetMyEntityId();
                eventMessage.Model.CustomProperties["AvailableMyEntities"] = _myEntityService.GetAllMyEntities();
            }
        }
        
        // 模型接收)        public void HandleEvent(ModelReceivedEvent<CustomerModel> eventMessage)
        {
            var customer = _customerService.GetCustomerById(eventMessage.Model.Id);
            if (customer != null)
            {
                // 保存自定义字段)                if (eventMessage.Model.CustomProperties.TryGetValue("MyEntityId", out var myEntityIdObj) &&
                    int.TryParse(myEntityIdObj).ToString(), out var myEntityId))
                {
                    customer.SetMyEntityId(myEntityId);
                    _customerService.UpdateCustomer(customer);
                }
            }
        }
    }
}

1.12.2 使用视图组件

[ViewComponent(Name = "AdminCustomerMyPlugin")]
public class AdminCustomerMyPluginViewComponent : NopViewComponent
{
    private readonly IMyEntityService _myEntityService;
    private readonly ICustomerService _customerService;
    
    public AdminCustomerMyPluginViewComponent(IMyEntityService myEntityService, ICustomerService customerService)
    {
        _myEntityService = myEntityService;
        _customerService = customerService;
    }
    
    public IViewComponentResult Invoke(int customerId)
    {
        var customer = _customerService.GetCustomerById(customerId);
        var model = new MyPluginCustomerModel
        {
            CustomerId = customerId,
            MyEntityId = customer.GetMyEntityId(),
            AvailableMyEntities = _myEntityService.GetAllMyEntities()
        };
        
        return View("~/Plugins/Custom.MyPlugin/Views/Admin/CustomerMyPlugin.cshtml", model);
    }
}

1.13 全局动作过滤器与INopStartup接口

1.13.1 创建全局过滤)

using Microsoft.AspNetCore.Mvc.Filters;
using Nop.Core;

namespace Nop.Plugin.Custom.MyPlugin.Filters
{
    /// <summary>
    /// 全局动作过滤)    /// </summary>
    public class MyPluginActionFilter : IActionFilter
    {
        private readonly IWorkContext _workContext;
        
        public MyPluginActionFilter(IWorkContext workContext)
        {
            _workContext = workContext;
        }
        
        public void OnActionExecuting(ActionExecutingContext context)
        {
            // 执行前逻辑
        }
        
        public void OnActionExecuted(ActionExecutedContext context)
        {
            // 执行后逻辑
        }
    }
}

1.13.2 使用INopStartup注册

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Nop.Core.Infrastructure;
using Nop.Plugin.Custom.MyPlugin.Filters;

namespace Nop.Plugin.Custom.MyPlugin.Infrastructure
{
    /// <summary>
    /// 插件启动配置
    /// </summary>
    public class MyPluginStartup : INopStartup
    {
        /// <summary>
        /// 配置服务
        /// </summary>
        public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
        {
            // 添加全局过滤)            services.Configure<MvcOptions>(options =>
            {
                options.Filters.Add(typeof(MyPluginActionFilter));
            });
        }
        
        /// <summary>
        /// 配置请求管道
        /// </summary>
        public void Configure(IApplicationBuilder application)
        {
            // 配置中间)        }
        
        public int Order => 1000;
    }
}

1.14 在插件中添加计划任务

1.14.1 创建计划任务)

using Nop.Core.Domain.Tasks;
using Nop.Plugin.Custom.MyPlugin.Services;

namespace Nop.Plugin.Custom.MyPlugin.Tasks
{
    /// <summary>
    /// MyEntity清理任务
    /// </summary>
    public class MyEntityCleanupTask : IScheduleTask
    {
        private readonly IMyEntityService _myEntityService;
        
        public MyEntityCleanupTask(IMyEntityService myEntityService)
        {
            _myEntityService = myEntityService;
        }
        
        /// <summary>
        /// 执行任务
        /// </summary>
        public async Task ExecuteAsync()
        {
            // 执行清理逻辑
            var oldEntities = _myEntityService.GetAllMyEntities()
                .Where(e => e.CreatedOnUtc < DateTime.UtcNow.AddMonths(-6))
                .ToList();
                
            foreach (var entity in oldEntities)
            {
                _myEntityService.DeleteMyEntity(entity);
            }
        }
    }
}

1.14.2 注册计划任务

using Nop.Core.Domain.Tasks;
using Nop.Services.Tasks;

namespace Nop.Plugin.Custom.MyPlugin.Infrastructure
{
    public class ScheduleTaskRegistrar : IStartupTask
    {
        private readonly IScheduleTaskService _scheduleTaskService;
        
        public ScheduleTaskRegistrar(IScheduleTaskService scheduleTaskService)
        {
            _scheduleTaskService = scheduleTaskService;
        }
        
        public void Execute()
        {
            // 注册或更新计划任)            var task = _scheduleTaskService.GetTaskByType(typeof(MyEntityCleanupTask).FullName);
            
            if (task == null)
            {
                task = new ScheduleTask
                {
                    Name = "MyEntity Cleanup Task",
                    Type = typeof(MyEntityCleanupTask).FullName,
                    Seconds = 86400, // 每天执行一)                    Enabled = true,
                    StopOnError = false
                };
                _scheduleTaskService.InsertTask(task);
            }
            else
            {
                task.Seconds = 86400;
                task.Enabled = true;
                _scheduleTaskService.UpdateTask(task);
            }
        }
        
        public int Order => 1000;
    }
}

2. 导航

上一章:4.6 插件安装、卸载与更新机制

下一章:5.1 主题架构与工作原理

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐