zoukankan      html  css  js  c++  java
  • 我的NopCommerce之旅(9): 编写Plugin实例

    一、基础介绍

      ——In computing, a plug-in (or plugin) is a set of software components that add specific abilities to a larger software application (Wikipedia).

      Plugin,即插件,用来做NopCommerce的功能扩展。NopCommerce源码本身提供了一些插件供参考使用。本篇文章通过阅读官方文档进行实践总结,主要讲解如何编写一个数据持久化的NopCommerce插件。

    二、效果展示

      当打开前台产品详细时,系统会自动追踪并记录用户访问的产品信息、访问的用户信息及其IP地址信息等。

      

    三、编写步骤

      1.新建项目,项目名为Nop.Plugin.Other.ProductViewTracker,注意项目位置需统一放置在..plugins下,与输出位置保持统一。

      

      2.添加Description.txt文件,该文件为必备文件,且格式需保持统一。该文件描述插件相关信息,并作为系统识别插件依据。

      

      3.添加必要的文件夹,名称可根据个人习惯,这里为保持命名规则统一,命名如下Controllers、Data、Domain、Services。

      

      4.添加dll引用,且设置属性"Copy Local"为False。本项目引用如图所示。

       

      5.添加实体类及其数据库映射,添加数据库访问上下文。

        5.1 实体类TrackingRecord,继承基类BaseEntity

     1 using Nop.Core;
     2 
     3 namespace Nop.Plugin.Other.ProductViewTracker.Domain
     4 {
     5     public class TrackingRecord : BaseEntity
     6     {
     7         public virtual int ProductId { get; set; }
     8         public virtual string ProductName { get; set; }
     9         public virtual int CustomerId { get; set; }
    10         public virtual string IpAddress { get; set; }
    11         public virtual bool IsRegistered { get; set; }
    12     }
    13 }

        5.2 数据库表映射类TrackingRecordMap,继承EntityTypeConfiguration<T>

     1 using Nop.Plugin.Other.ProductViewTracker.Domain;
     2 using System.Data.Entity.ModelConfiguration;
     3 
     4 namespace Nop.Plugin.Other.ProductViewTracker.Data
     5 {
     6     public class TrackingRecordMap : EntityTypeConfiguration<TrackingRecord>
     7     {
     8         public TrackingRecordMap()
     9         {
    10             ToTable("ProductViewTracking");
    11 
    12             HasKey(m => m.Id);
    13             Property(m => m.ProductId);
    14             Property(m => m.ProductName).HasMaxLength(400);
    15             Property(m => m.IpAddress);
    16             Property(m => m.CustomerId);
    17             Property(m => m.IsRegistered);
    18         }
    19     }
    20 }

        5.3 数据库访问上下文,安装插件时生成并执行建表脚本,卸载插件时删除该表

     1 using Nop.Data;
     2 using System;
     3 using System.Collections.Generic;
     4 using System.Data.Entity;
     5 using Nop.Core;
     6 using System.Data.Entity.Infrastructure;
     7 
     8 namespace Nop.Plugin.Other.ProductViewTracker.Data
     9 {
    10     public class TrackingRecordObjectContext : DbContext, IDbContext
    11     {
    12         public TrackingRecordObjectContext(string nameOrConnectionString) : base(nameOrConnectionString) { }
    13 
    14         #region Implementation of IDbContext
    15 
    16         public bool AutoDetectChangesEnabled
    17         {
    18             get
    19             {
    20                 throw new NotImplementedException();
    21             }
    22 
    23             set
    24             {
    25                 throw new NotImplementedException();
    26             }
    27         }
    28 
    29         public bool ProxyCreationEnabled
    30         {
    31             get
    32             {
    33                 throw new NotImplementedException();
    34             }
    35 
    36             set
    37             {
    38                 throw new NotImplementedException();
    39             }
    40         }
    41 
    42         public void Detach(object entity)
    43         {
    44             throw new NotImplementedException();
    45         }
    46 
    47         public int ExecuteSqlCommand(string sql, bool doNotEnsureTransaction = false, int? timeout = default(int?), params object[] parameters)
    48         {
    49             throw new NotImplementedException();
    50         }
    51 
    52         public IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params object[] parameters) where TEntity : BaseEntity, new()
    53         {
    54             throw new NotImplementedException();
    55         }
    56 
    57         public IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters)
    58         {
    59             throw new NotImplementedException();
    60         }
    61 
    62         public new IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity
    63         {
    64             return base.Set<TEntity>();
    65         }
    66 
    67         protected override void OnModelCreating(DbModelBuilder modelBuilder)
    68         {
    69             modelBuilder.Configurations.Add(new TrackingRecordMap());
    70 
    71             base.OnModelCreating(modelBuilder);
    72         }
    73 
    74         #endregion
    75 
    76         public string CreateDatabaseInstallationScript()
    77         {
    78             return ((IObjectContextAdapter)this).ObjectContext.CreateDatabaseScript();
    79         }
    80 
    81         public void Install()
    82         {
    83             Database.SetInitializer<TrackingRecordObjectContext>(null);
    84 
    85             Database.ExecuteSqlCommand(CreateDatabaseInstallationScript());
    86             SaveChanges();
    87         }
    88 
    89         public void Uninstall()
    90         {
    91             var dbScript = "DROP TABLE ProductViewTracking";
    92             Database.ExecuteSqlCommand(dbScript);
    93             SaveChanges();
    94         }
    95     }
    96 }

      6.添加业务服务类。

        6.1 服务接口

     1 using Nop.Plugin.Other.ProductViewTracker.Domain;
     2 
     3 namespace Nop.Plugin.Other.ProductViewTracker.Services
     4 {
     5     public interface IViewTrackingService
     6     {
     7         /// <summary>
     8         /// Logs the specified record.
     9         /// </summary>
    10         /// <param name="record">The record.</param>
    11         void Log(TrackingRecord record);
    12     }
    13 }

        6.2 业务服务类

     1 using Nop.Core.Data;
     2 using Nop.Plugin.Other.ProductViewTracker.Domain;
     3 
     4 namespace Nop.Plugin.Other.ProductViewTracker.Services
     5 {
     6     public class ViewTrackingService : IViewTrackingService
     7     {
     8         private readonly IRepository<TrackingRecord> _trackingRecordRepository;
     9 
    10         public ViewTrackingService(IRepository<TrackingRecord> trackingRecordRepository)
    11         {
    12             _trackingRecordRepository = trackingRecordRepository;
    13         }
    14 
    15         public void Log(TrackingRecord record)
    16         {
    17             _trackingRecordRepository.Insert(record);
    18         }
    19     }
    20 }

      7.实现依赖注入的注册接口。

     1 using Nop.Core.Infrastructure.DependencyManagement;
     2 using Autofac;
     3 using Nop.Core.Configuration;
     4 using Nop.Core.Infrastructure;
     5 using Nop.Plugin.Other.ProductViewTracker.Services;
     6 using Nop.Web.Framework.Mvc;
     7 using Nop.Plugin.Other.ProductViewTracker.Data;
     8 using Nop.Data;
     9 using Nop.Plugin.Other.ProductViewTracker.Domain;
    10 using Nop.Core.Data;
    11 using Autofac.Core;
    12 
    13 namespace Nop.Plugin.Other.ProductViewTracker
    14 {
    15     public class DependencyRegistrar : IDependencyRegistrar
    16     {
    17         private const string CONTEXT_NAME = "nop_object_context_product_view_tracker";
    18 
    19         public void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config)
    20         {
    21             builder.RegisterType<ViewTrackingService>().As<IViewTrackingService>().InstancePerLifetimeScope();
    22 
    23             //data context
    24             this.RegisterPluginDataContext<TrackingRecordObjectContext>(builder, CONTEXT_NAME);
    25 
    26             //override required repository with our custom context
    27             builder.RegisterType<EfRepository<TrackingRecord>>()
    28                 .As<IRepository<TrackingRecord>>()
    29                 .WithParameter(ResolvedParameter.ForNamed<IDbContext>(CONTEXT_NAME))
    30                 .InstancePerLifetimeScope();
    31         }
    32 
    33         public int Order
    34         {
    35             get { return 1; }
    36         }
    37     }
    38 }

      8.添加MVC Controller。

     1 using Nop.Core;
     2 using Nop.Core.Domain.Catalog;
     3 using Nop.Core.Domain.Customers;
     4 using Nop.Core.Plugins;
     5 using Nop.Plugin.Other.ProductViewTracker.Domain;
     6 using Nop.Plugin.Other.ProductViewTracker.Services;
     7 using Nop.Services.Catalog;
     8 using Nop.Web.Framework.Controllers;
     9 using System.Web.Mvc;
    10 
    11 namespace Nop.Plugin.Other.ProductViewTracker.Controllers
    12 {
    13     public class TrackingController : BasePluginController
    14     {
    15         private readonly IProductService _productService;
    16         private readonly IViewTrackingService _viewTrackingService;
    17         private readonly IWorkContext _workContext;
    18 
    19         public TrackingController(IWorkContext workContext,
    20             IViewTrackingService viewTrackingService,
    21             IProductService productService,
    22             IPluginFinder pluginFinder)
    23         {
    24             _workContext = workContext;
    25             _viewTrackingService = viewTrackingService;
    26             _productService = productService;
    27         }
    28 
    29         [ChildActionOnly]
    30         public ActionResult Index(int productId)
    31         {
    32             //Read from the product service
    33             Product productById = _productService.GetProductById(productId);
    34 
    35             //If the product exists we will log it
    36             if (productById != null)
    37             {
    38                 //Setup the product to save
    39                 var record = new TrackingRecord();
    40                 record.ProductId = productId;
    41                 record.ProductName = productById.Name;
    42                 record.CustomerId = _workContext.CurrentCustomer.Id;
    43                 record.IpAddress = _workContext.CurrentCustomer.LastIpAddress;
    44                 record.IsRegistered = _workContext.CurrentCustomer.IsRegistered();
    45 
    46                 //Map the values we're interested in to our new entity
    47                 _viewTrackingService.Log(record);
    48             }
    49 
    50             //Return the view, it doesn't need a model
    51             return Content("");
    52         }
    53     }
    54 }

      9.实现路由接口。

     1 using Nop.Web.Framework.Mvc.Routes;
     2 using System.Web.Mvc;
     3 using System.Web.Routing;
     4 
     5 namespace Nop.Plugin.Other.ProductViewTracker
     6 {
     7     public class RouteProvider : IRouteProvider
     8     {
     9         public int Priority
    10         {
    11             get
    12             {
    13                 return 0;
    14             }
    15         }
    16 
    17         public void RegisterRoutes(RouteCollection routes)
    18         {
    19             routes.MapRoute("Nop.Plugin.Other.ProductViewTracker.Log",
    20                  "tracking/productviews/{productId}",
    21                  new { controller = "Tracking", action = "Index" },
    22                  new[] { "Nop.Plugin.Other.ProductViewTracker.Controllers" }
    23             );
    24         }
    25     }
    26 }

      10.添加插件类,继承插件基类,重载安装和卸载方法。

     1 using Nop.Core.Plugins;
     2 using Nop.Plugin.Other.ProductViewTracker.Data;
     3 
     4 namespace Nop.Plugin.Other.ProductViewTracker
     5 {
     6     public class ProductViewTrackerPlugin : BasePlugin
     7     {
     8         private readonly TrackingRecordObjectContext _context;
     9 
    10         public ProductViewTrackerPlugin(TrackingRecordObjectContext context)
    11         {
    12             _context = context;
    13         }
    14 
    15         public override void Install()
    16         {
    17             _context.Install();
    18             base.Install();
    19         }
    20 
    21         public override void Uninstall()
    22         {
    23             _context.Uninstall();
    24             base.Uninstall();
    25         }
    26     }
    27 }

      11.在NopCommerce的前台,加入插件的应用代码。这里,我们在页面Nop.WebViewsProductProductTemplate.Simple.cshtml中插入应用代码。

    @Html.Action("Index", "Tracking", new { productId = Model.Id })

      如图

      

  • 相关阅读:
    Linux 下的类似Windows下Everything的搜索工具
    windows和linux环境下制作U盘启动盘
    程序调试手段之gdb, vxworks shell
    LeetCode 1021. Remove Outermost Parentheses (删除最外层的括号)
    LeetCode 1047. Remove All Adjacent Duplicates In String (删除字符串中的所有相邻重复项)
    LeetCode 844. Backspace String Compare (比较含退格的字符串)
    LeetCode 860. Lemonade Change (柠檬水找零)
    LeetCode 1221. Split a String in Balanced Strings (分割平衡字符串)
    LeetCode 1046. Last Stone Weight (最后一块石头的重量 )
    LeetCode 746. Min Cost Climbing Stairs (使用最小花费爬楼梯)
  • 原文地址:https://www.cnblogs.com/devilsky/p/5376401.html
Copyright © 2011-2022 走看看