Proposal of a modified nopCommerce architecture to extend entities

1 2 3 4 >
Posted: May 08, 2014 at 8:06 AM Quote #122480
Hey folks,

often I got problems to extend an entity with a custom attribute in nopCommerce while developing plugins. The tutorial https://www.nopcommerce.com/docs/73/updating-an-existing-entity-how-to-add-a-new-property.aspx is editing the core of nopCommerce. To make use of a new version of nopCommerce I need to backup all edited files and manually merge them onto the new version.

Another solution is to the usage of generic attributes. In this case I can’t use validations or database mappings. Additionally all attributes are saved as a string and slows down the performance of nopCommerce if a huge of these generic attributes is used.

My proposal for extending entities is described into four steps and shows up a modified architecture of nopCommerce that could be used in next major versions of nopCommerce:

Step 1: Extending Entities

First I need to declare the extending properties to make use of them in the business logic.
All entities are located in nop.core.Domain and all these classes are partial classes.
So it is possible to extend an entity with a partial class without touching the original file.


Step 2: Extending Entity-Maps

When I have to declare some properties or relationships for the database I need a look at the entity maps. They are located in Nop.Data.Mapping. In this scenario I can’t extend the class with a partial-class because all declarations are done in a constructor.

The only solution is to create a separate abstract base class, let’s say NopCommerceTypeConfiguration, because the mapping classes extend  EntityTypeConfiguration<T>. So now I can declare a protected virtual void PostInitialize() method in the new base-class which is calling the method in the constructor.


namespace Nop.Data.Customization.Mapping.Configuration
{
  public abstract class NopCommerceTypeConfiguration<T> : EntityTypeConfiguration<T> where T : class
  {
    protected NopCommerceTypeConfiguration()
    {
      PostInitialize();
    }
  
    protected virtual void PostInitialize() { }
  }
}


Furthermore I can go ahead and create partial-extended classes and make use of the PostInitialize method to declare additional restrictions. E.g. Nop.Data.Mapping.Catalog.ProductMap:


namespace Nop.Data.Mapping.Catalog
{
  public partial class ProductMap : NopCommerceTypeConfiguration<Product>
  {
    public ProductMap()
    {
      this.ToTable( "Product" );
      this.HasKey( p => p.Id );
      /* ... */
    }
  }
}


the partial extended classes could be looks like:


namespace Nop.Data.Mapping.Catalog
{
  public partial class ProductMap
  {
    protected override void PostInitialize()
    {
      this.Property( p => p.CustomProperty).HasMaxLength( 5 );
      /* ... */
    }
  }
}


The only important thing is to change the type from EntityTypeConfiguration to NopCommerceTypeConfiguration in the OnModelCreating method of the class Nop.Data.NopObjectContext.


protected override void OnModelCreating( DbModelBuilder modelBuilder )
    {
      /* ... */
      var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
      .Where( type => !String.IsNullOrEmpty( type.Namespace ) )
      .Where( type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof( NopCommerceTypeConfiguration<> ) );
      /* ... */
    }



Step 3: Extending Entity-Models

Now I need to edit the entity model. Unfortunately all entity models are not partial and also make use of declarations in constructors. So I need to edit all models located in Nop.Admin.Models, Nop.Web.Models and Nop.Framework.Models to be partial.

In this case all models extend the Nop.Web.Framework.Mvc.BaseNopEntityModel class. This class is partial and does not have a constructor. So this allows me to create a partial-extended class and create a PostInitialize Method like in Step 2 and call the method in the created constructor.


namespace Nop.Web.Framework.Mvc
{
  public partial class BaseNopEntityModel
  {
    public BaseNopEntityModel()
    {
      PostInitialize();
    }
  
    protected virtual void PostInitialize() { }
  }
}


Next I can simply partially extend the models.


Step 4: Extending Validators

If I need to declare some validation rules for my additional properties I need to extend the validators located in Nop.Admin.Models, Nop.Web.Models and Nop.Framework.Models.

Here I also need to edit all validators to be partial and insert a new abstract base class that contains a PostInitialize method called in the constructor between the validator class and the extending AbstractValidator<T> class of the Fluent Validation Framework like step 2.


To put all in a nutshell

If the following things are given it is much easier and much safer to extend and entity in nopCommerce. This make it uncomplicated to use continuous integration for updating new versions of nopCommerce without backup all edited files and manual merging them back to the new version.

- Entity-Maps, Validators needs an abstract base class between the actual extending with a constructor that is calling a protected virtual method.

- Change using type in OnModelCreating method in class Nop.Data.NopObjectContext.

- Declare all Entity-Models as partial.

- Create a PostInitialisze method that is called in the created constructor in class Nop.Web.Framework.Mvc.BaseNopEntityModel.
This post/answer is useful
21
This post/answer is not useful

Please login or register
to vote for this post.

(click on this box to dismiss)
Posted: May 08, 2014 at 8:27 AM Quote #122483
It all looks very good. The work item is here. Thanks a lot for suggestions.
This post/answer is useful
5
This post/answer is not useful

Please login or register
to vote for this post.

(click on this box to dismiss)
Join us at nopCommerce Days. Nov 16-17, New York. http://days17.nopcommerce.com/

Interested in the dedicated Premium support services provided by core developers? Please visit http://www.nopcommerce.com/supportservices.aspx

Regards,
Andrei Mazulnitsyn
Posted: May 08, 2014 at 9:35 AM Quote #122485
This proposal looks pretty cool. At the moment, it is really curcuitous to extend entities in a "clean" way. (as I described in my post https://www.nopcommerce.com/boards/t/29527/extending-entities-without-editing-the-nopcommerce-330-core.aspx). This solution looks much better. I hope it will find it's way into the nopCommerce core.
This post/answer is useful
1
This post/answer is not useful

Please login or register
to vote for this post.

(click on this box to dismiss)
Posted: May 12, 2014 at 9:21 PM Quote #122720
I agree that this seems more elegant than using Generic attributes.  It just feels right.
This post/answer is useful
1
This post/answer is not useful

Please login or register
to vote for this post.

(click on this box to dismiss)
Posted: July 16, 2014 at 1:43 AM Quote #126528
This is a really cool suggestion. It would be very nice if this would be realized in nopCommerce.
This post/answer is useful
1
This post/answer is not useful

Please login or register
to vote for this post.

(click on this box to dismiss)
Posted: August 11, 2014 at 8:09 AM Quote #128130
Done. Please see changeset 430d037b2ef4.

Again thanks a lot for this contribution!
This post/answer is useful
5
This post/answer is not useful

Please login or register
to vote for this post.

(click on this box to dismiss)
Join us at nopCommerce Days. Nov 16-17, New York. http://days17.nopcommerce.com/

Interested in the dedicated Premium support services provided by core developers? Please visit http://www.nopcommerce.com/supportservices.aspx

Regards,
Andrei Mazulnitsyn
Posted: August 11, 2014 at 11:25 AM Quote #128185
awesome Andrei. thank you.
This post/answer is useful
0
This post/answer is not useful

Please login or register
to vote for this post.

(click on this box to dismiss)
Posted: August 12, 2014 at 4:14 AM Quote #128232
I do a lot of work on NopCommere (Andrey it's fantastic thank you) and this sounds fantastic, but I am having trouble wrapping my head around how it works from the plugin writer's point of view. If somebody could explain it that would be great.
This post/answer is useful
2
This post/answer is not useful

Please login or register
to vote for this post.

(click on this box to dismiss)
Posted: August 27, 2014 at 5:05 AM Quote #129348
Sure wish somebody could do a write up on this
This post/answer is useful
1
This post/answer is not useful

Please login or register
to vote for this post.

(click on this box to dismiss)
Posted: September 12, 2014 at 3:45 AM Quote #130671
a.m. wrote:
Done. Please see changeset 430d037b2ef4.

Again thanks a lot for this contribution!


I proposed something very similar almost 2 years ago. If this is done, you can close this item: https://nopcommerce.codeplex.com/workitem/11274
This post/answer is useful
1
This post/answer is not useful

Please login or register
to vote for this post.

(click on this box to dismiss)
Francesc Castells

Software Architect
www.nopStuff.com
www.trainerinside.com
1 2 3 4 >
Premium support services
  • Dedicated premium support services provided by core developers are intended for persons who run mission critical websites, work on projects with tight deadlines, or want to get dedicated support.
Professional services
  • Want to open a new store? Want to take your store to the next level? Need a custom extension? We can customize nopCommerce to fit your store perfectly. Request a quote to get started.