NopCommerce-based development framework with source code and nopcommerce source code
. NET developers should all know that this famous high-quality B2C open-source project-nopCommerce, developed based on EntityFramework and MVC, has a transparent and well-structured solution, it also integrates the best features of open-source and commercial software. Official website address: http://www.nopcommerce.com/, Chinese website: http://www.nopcn.com /. After the download, the front and back ends are shown as follows. If you have not yet understood this project, we recommend that you download the code from the official website and run it locally to view the effect.
I have used this framework to develop many projects. In general, it is convenient and concise. I have integrated. NET to develop many common components and functions. I always wanted to share it, but I was busy with my work and didn't reach it. Recently I have time to write this article, this article will show how to extract the simplified framework of the source code and attach the source code (based on nopCommerce3.9 ). If you want to understand the Framework Structure and use it to develop projects, reading this article is valuable. Front-row prompt: the source code of this framework has been uploaded to GitHub: IWorkContext, plug-in, taskservice, logs, cache, and localization. Welcome to star. Your support is my motivation!
1. Understand the project structure
From the project structure, we can also see that the layer of Nop is very clear. First, let's look at the level chart I drew.
1. Presentation Layer)
It can also be called the application layer. It only focuses on front-end integration and does not involve any domain logic implementation. This layer is only for presentation and is dispensable for our framework. Therefore, this layer will be deleted when the framework is extracted.
2. Business Service Layer (Nop. Services)
The service layer of the entire system provides interfaces and implementations for each domain. This layer is very important. It provides the interface service for the presentation layer in the program. Whether the presentation layer uses mvc, winform, or webapi called for the app, services at this layer are required. However, services at this layer are mainly e-commerce services that are useless to our framework. Therefore, all services will be deleted in this framework and only one test service class and interface will be added, you should add interfaces and services at this layer to the project.
3. Data layer (Nop. Data)
Nop uses ef and sqlserver databases in the data layer warehousing implementation. If you want to expand, you can also use other ORM ing libraries and databases at this layer. Most of the features at this layer will be retained in the framework.
4. Infrastructure layer (Nop. Core)
Including cache implementation, configuration, and domain model. Some functions will be retained in the framework, and the Domain model will be removed from this layer for separate projects. Why should we do this? Because there are usually many Domain layer adjustments, therefore, I usually create a separate Project for the Domain. Of course, you can also leave it unadjusted, but the framework has made this adjustment.
Ii. Delete business-related code
We have an understanding of the entire code hierarchy of Nop and started to modify the project source code based on the following two points: 1. The framework is sufficiently simplified and there is no e-commerce business. 2. The core functions are retained. We recommend that you copy the source code before starting.
1. Test Project:Under the Tests folder is a test project, which is not required. you can remove it all and develop a specific business. You can add a test project separately. Because it is a test project, the entire project can run after deletion.
2. Presentation layer:The three projects here are the modules shared by the front-end, backend, and two projects. Like the test project, we also remove all items here.
3. Plugin project:Plug-in projects, like 1 and 2, are not required. Remove all plug-in projects. There are only three projects left. (Welcome to github of this project. I will write an article to introduce how to add plug-ins later ).
Nop. Services: business service layer, which is the internal and external interface layer of the assembly and needs to be retained. Delete all related business services, including logs, help, tasks, and other system-related services to better display the structure of the entire system. Add a test class without writing anything.
Nop. Data: Data layer project. This layer is not adjusted. Only the EF ing Class of EF is deleted.
Nop. Core: infrastructure layer. Delete the Domain related to the e-commerce business and create the project Nop. Domain.
An error is reported. IWorkContext (working context, used to obtain user information and other data) depends on Domain to delete it. This process may delete many files until the project does not report any errors. After the completion, our project structure is as follows. Note that we moved the entity base class in Nop. Core to Nop. Domain. At this step, our basic framework structure has been outlined.
3. Add database, data entity, ing, and Business Layer Code
1. In local Sqlserver, create a database MyProject and add the table Test.
USE [MyProject]GO /****** Object: Table [dbo].[Test] Script Date: 05/24/2017 23:51:21 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [dbo].[Test]([Id] [int] NOT NULL,[Name] [nvarchar](50) NOT NULL,[Description] [nvarchar](200) NULL,[CreateDate] [datetime] NULL,CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED[Id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]
2. Add object classes and mappings. Create the Test directory under the Domain project and add TestEntity. Create a Test directory under the Data project Mapping and add the EF ing Class.
public class TestEntity: BaseEntity{ public virtual string Name { get; set; } public virtual string Description { get; set; } public virtual DateTime? CreateDate { get; set; }}
3. Add the business layer method.
In the Nop. Services Project, add several common CURD methods under the interfaces and classes we added earlier and implement them. In this way, we have implemented the code at the business layer.
/// <summary>/// Test service interface/// </summary>public partial interface ITestService{/// <summary>/// Gets all tests/// </summary>/// <returns>Tests</returns>IList<TestEntity> GetAllTests(); /// <summary>/// Gets a test/// </summary>/// <param name="testId">The test identifier</param>/// <returns>Test</returns>TestEntity GetTestById(int testId);/// <summary>/// Inserts a test/// </summary>/// <param name="test">Test</param>void InsertTest(TestEntity test);/// <summary>/// Updates the test/// </summary>/// <param name="test">Test</param>void UpdateTest(TestEntity test);/// <summary>/// Deletes a test/// </summary>/// <param name="test">Test</param>void DeleteTest(TestEntity test);}
/// <summary>/// Test service/// </summary>public partial class TestService : ITestService{#region Constants#endregion#region Fields private readonly IRepository<TestEntity> _testRepository;#endregion#region Ctorpublic TestService(IRepository<TestEntity> testRepository){this._testRepository = testRepository;}#endregion#region Methods /// <summary>/// Gets all tests/// </summary>/// <returns>Tests</returns>public virtual IList<TestEntity> GetAllTests(){return _testRepository.Table.Where(p => p.Name != null).ToList();}/// <summary>/// Gets a topic/// </summary>/// <param name="testId">The test identifier</param>/// <returns>Test</returns>public virtual TestEntity GetTestById(int testId){if (testId == 0)return null;return _testRepository.GetById(testId);} /// <summary>/// Inserts a test/// </summary>/// <param name="test">Test</param>public virtual void InsertTest(TestEntity test){if (test == null)throw new ArgumentNullException("test");_testRepository.Insert(test); }/// <summary>/// Updates the test/// </summary>/// <param name="test">Test</param>public virtual void UpdateTest(TestEntity test){if (test == null)throw new ArgumentNullException("test");_testRepository.Update(test);}/// <summary>/// Deletes a test/// </summary>/// <param name="test">Test</param>public virtual void DeleteTest(TestEntity test){if (test == null)throw new ArgumentNullException("test");_testRepository.Delete(test);}#endregion}
4. Add a Presentation Project
With the service, you can now add a performance Layer project for testing. Why not write test projects directly? Because the testing project uses Mock to simulate data, the entire function cannot be fully displayed.
1. Add an mvc template project and introduce Autofac and Autofac. Mvc5 through nuget.
2. Add the container registration class DependencyRegistrar to implement the IDependencyRegistrar interface. This step is critical. We will inject the interfaces and implementation classes we will use into the container.
/// <Summary> /// Dependency registrar // </summary> public class DependencyRegistrar: IDependencyRegistrar {// <summary> // Register services and interfaces /// </summary> /// <param name = "builder"> Container builder </param>/ // <param name = "typeFinder"> Type finder </param> // <param name = "config"> Config </param> public virtual void Register (ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config) {// inject ObjectContextbuilder. register <IDbContext> (c => new NopObjectContext ("test ")). instanceperlifetimescript (); // inject ef to the warehouse builder. registerGeneric (typeof (EfRepository <> )). as (typeof (IRepository <> )). instanceperlifetimescript (); // inject Service and interface builder. registerAssemblyTypes (typeof (TestService ). assembly ). asImplementedInterfaces (). instanceperlifetimescript (); // inject controllersbuilder. registerControllers (typeFinder. getAssemblies (). toArray ();} // <summary> // Order of this dependency registrar implementation // </summary> public int Order {get {return 2 ;}}}
3. Add a Database Access Node to the configuration file
Copy codeThe Code is as follows: <add name = "test" connectionString = "Data Source = .; initial Catalog = MyProject; Integrated Security = False; Persist Security Info = False; User ID = sa; Password = sa1234 "providerName =" System. data. sqlClient "/>
4. Add the initialization engine context when the application starts.
When the project is started, NopEngine will report an error because we didn't use Nopconfig to configure the project. Comment out NopConfig injection in the RegisterDependencies method, and comment out the relevant code during the Initialize process. In this way, the class is injected into the container through Autofac.
Public class MvcApplication: System. web. httpApplication {protected void Application_Start () {AreaRegistration. registerAllAreas (); FilterConfig. registerGlobalFilters (GlobalFilters. filters); RouteConfig. registerRoutes (RouteTable. routes); BundleConfig. registerBundles (BundleTable. bundles); // engine context initialization EngineContext. initialize (false );}}
// Comment NopConfig injection in the RegisterDependencies method // builder. registerInstance (config ). as <NopConfig> (). singleInstance (); public void Initialize (NopConfig config) {// register dependenciesRegisterDependencies (config); // If config is not used, temporarily comment out // register mapper configurations // RegisterMapperConfiguration (config ); // startup tasks does not enable the task, note // if (! Config. IgnoreStartupTasks) // {// RunStartupTasks ();//}}
5. Add the test code to the controller. Add the service to HomeController and initialize it in the constructor. The instance is automatically injected after the system starts. Through the breakpoint, we can see that the data is successfully added to the database.
Public class HomeController: Controller {public ITestService _ testService; public HomeController (ITestService testService) {_ testService = testService;} public ActionResult Index () {var entity = new TestEntity () {CreateDate = DateTime. now, Description = "Description 2", Name = "Test Data 2"}; _ testService. insertTest (entity); var tests = _ testService. getAllTests (); return View ();}
5. Extend to Webapi, Winform, and WPF
Now add a winform project and add relevant code in the same step. In Winform, we can also use business services.
1. Install autofac and entityframework through Nuget to add references under the project Libraries.
2. Add the dependent registration class. Because it is a winform project, DependencyRegistrar needs to be adjusted here. It is recommended to define an empty interface IRegistrarForm and implement IRegistrarForm by injecting the Form.
/// <Summary> /// Dependency registrar // </summary> public class DependencyRegistrar: IDependencyRegistrar {// <summary> // Register services and interfaces /// </summary> /// <param name = "builder"> Container builder </param>/ // <param name = "typeFinder"> Type finder </param> // <param name = "config"> Config </param> public virtual void Register (ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config) {// inject ObjectContextbuilder. register <IDbContext> (c => new NopObjectContext ("test ")). instanceperlifetimescript (); // inject ef to the warehouse builder. registerGeneric (typeof (EfRepository <> )). as (typeof (IRepository <> )). instanceperlifetimescript (); // inject Service and interface builder. registerAssemblyTypes (typeof (TestService ). assembly ). asImplementedInterfaces (). instanceperlifetimescript (); // inject controllers // builder. registerControllers (typeFinder. getAssemblies (). toArray (); // inject formsvar types = AppDomain. currentDomain. getAssemblies (). selectiterator (a =>. getTypes (). where (t => t. getInterfaces (). contains (typeof (IRegistrarForm )))). toArray (); foreach (var formtype in types) {builder. registerAssemblyTypes (formtype. assembly) ;}/// <summary> // Order of this dependency registrar implementation /// </summary> public int Order {get {return 2 ;}}}
3. add EngineContext at startup. initialize (false): when the project is started, an error is reported. Because winform cannot be executed, make some adjustments to the method. Add an isForm parameter to indicate whether it is a winform. The default value is false.
/// <Summary> // Initializes a static instance of the Nop factory. /// </summary> /// <param name = "forceRecreate"> Creates a new factory instance even though the factory has been previusly initialized. </param> /// <param name = "isWinForm"> whether the client program </param> [MethodImpl (MethodImplOptions. synchronized)] public static IEngine Initialize (bool forceRecreate, bool isWinForm = false) {if (Singleton <IEngine>. Instance = null | forceRecreate) {Singleton <IEngine>. Instance = new NopEngine (); NopConfig config = null; if (! IsWinForm) {config = ConfigurationManager. getSection ("NopConfig") as NopConfig;} else {// If winform is used, use this code to read the configuration and initialize NopConfig var deleettings = ConfigurationManager. deleetask; foreach (var key in deleetask. allKeys) {}} Singleton <IEngine>. instance. initialize (config);} return Singleton <IEngine>. instance ;}
Static class Program {// <summary> // main entry point of the application. /// </Summary> [STAThread] static void Main () {Application. enableVisualStyles (); Application. setCompatibleTextRenderingDefault (false); // Application. run (new Form1 (); // engine context initialization EngineContext. initialize (false, true); Application. run (EngineContext. current. resolve <Form1> ());}}
4. In the From1 test, the method at the business layer is successfully called. Here we did not instantiate the ITestService, but handed over to the dependency injection for automatic implementation.
Public partial class Form1: Form, IRegistrarForm {private ITestService _ testService; public Form1 (ITestService testService) {InitializeComponent (); _ testService = testService; // if the form is not injected, EngineContext can be used. current. resolve <ITestService> (); get instance} private void button#click (object sender, EventArgs e) {var tests = _ testService. getAllTests ();}}
So far, the Nop-Based Simplified development framework has been basically completed. If you are interested, we suggest you follow this project on github: https://github.com/dreling8/nop.framework. welcome to starstar. Your support is my motivation!
The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.