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 })

      如图

      

  • 相关阅读:
    CF 842A
    Codeforces 842B
    CodeForces
    CodeForces 359A Table
    Find them, Catch them POJ
    剪花布条 HDU
    关于map的学习笔记
    ASP.NET MVC 中将数据从View传递到控制器中的三种方法(表单数据绑定)
    SQL Delta实用案例介绍 (对应软件)
    SQL Select count(*)和Count(1)的区别和执行方式及SQL性能优化
  • 原文地址:https://www.cnblogs.com/devilsky/p/5376401.html
Copyright © 2011-2022 走看看