Search code examples
c#asp.net-coremodel-view-controller

How to extend existing third party model?


I have a third party library i am using. The have provided some of the classes for me to use to transfer data from one page to another, but i dont have the source code to make changes, for example

public class Customer
{
public string Name {get;set}
public Additional AdditionalDetails {get;set}
}

In this example i want to extend the Additional class and add properties to it without breaking the existing workings.

My controller and view works by passing in the customer class but all i want to do is add a new property to the Additional class.

I have tried to create a partial class but that didnt work and received the warning partial class with single part.

I then tried to create the class as

public class Additional

under the same namespace in my project and add the new property but that too didnt work (property didnt show).

Is there a way for me to extend this Additional class without breaking the existing code?


Solution

  • Is there a way for me to extend this Additional class without breaking the existing code?

    In order extend the Additional class and add properties to it without breaking the existing workings, we could follow couple of approach, one of the way could be Wrapper Class

    This approach allows you to keep using the existing third-party class (Customer and Additional) without any modifications to their usage while adding new properties to Additional.

    First of all, I would be creating a customer with existing details, then need to Wrap the AdditionalDetails where would would inlcude the new proeprty and finally would build view model to pass the data to the view.

    Let's have a look in practice:

    Existing Class:

    public class Additional
    {
        public string ExistingProperty { get; set; }
    }
    
    
    public class Customer
    {
        public string Name { get; set; }
        public Additional AdditionalDetails { get; set; }
    }
    
    
    public interface IAdditional
    {
        string ExistingProperty { get; }
    }
    

    Wrapper Class:

    public class ExtendedAdditional : IAdditional
    {
        private readonly Additional _original;
    
        public ExtendedAdditional(Additional original)
        {
            _original = original ?? throw new ArgumentNullException(nameof(original));
        }
    
        public string ExistingProperty => _original.ExistingProperty;
    
        public string NewProperty { get; set; }
    }
    

    View Model:

    public class CustomerViewModel
    {
        public Customer Customer { get; set; }
        public ExtendedAdditional ExtendedAdditional { get; set; }
    }
    

    Controller:

    public IActionResult Index()
     {
         
         var customer = new Customer
         {
             Name = "Kiron Test",
             AdditionalDetails = new Additional { ExistingProperty = "Existing Value" }
         };
    
        
         var extendedAdditional = new ExtendedAdditional(customer.AdditionalDetails)
         {
             NewProperty = "New Value"
         };
    
         
         var model = new CustomerViewModel
         {
             Customer = customer,
             ExtendedAdditional = extendedAdditional
         };
    
         return View(model);
     }
    

    View:

    @model CustomerViewModel
    
    <h2>Customer Details</h2>
    <p>Name: @Model.Customer.Name</p>
    
    <h3>Additional Details</h3>
    <p>Existing Property: @Model.ExtendedAdditional.ExistingProperty</p>
    <p>New Property: @Model.ExtendedAdditional.NewProperty</p>
    

    Output:

    enter image description here

    enter image description here

    Note: In most cases, using a wrapper class (ExtendedAdditional) is considered more elegant and aligns better with principles of object-oriented design and separation of concerns. It provides a clear boundary between your application's logic and the third-party library's implementation.