Search code examples
c#restconstructorinstantiation

C# Initialize class properties from REST client inside constructor


I've searched a lot and I think this is possible, but I feel like I am just blocked from knowing how to properly format it.

I have a class representing a product that is a relation class from our CRM to Magento.

Inside the constructor, I have to do some stuff like this...

public Product(IBaseProduct netforumProduct, MagentoClient client)
{
    Product existingMagentoProduct = client.GetProductBySku(netforumProduct.Code);

    if (existingMagentoProduct != null)
    {
        this.id = existingMagentoProduct.id;
        this.name = existingMagentoProduct.name;

        ... many of them ...

        this.visibility = existingMagentoProduct.visibility;
        this.extension_attributes.configurable_product_links = existingMagentoProduct.extension_attributes.configurable_product_links;
    }
    else
    {
        //  its a new product, new up the objects
        this.id = -1;
        this.product_links = new List<ProductLink>();
        this.options = new List<Option>();
        this.custom_attributes = new List<CustomAttribute>();
        this.media_gallery_entries = new List<MediaGalleryEntry>();
        this.extension_attributes = new ExtensionAttributes();
        this.status = 0; // Keep all new products disabled so they can be added to the site and released on a specific day (this is a feature, not an issue / problem).
        this.attribute_set_id = netforumProduct.AttributeSetId;
        this.visibility = 0;

    }
}

It seems silly to have to initialize all of the properties like that. I could use a mapper but that seems like a bandaid. I have to see if the product exists in magento first, and populate its ID and values, otherwise whenever I save the product it creates an additional one.

I considered doing the class constructor calling a static method, but I couldn't get the syntax right.

It might just be too late and I need to think about something else for awhile.


Solution

  • If you must do it in the constructor, you can get rid of a lot of code by first setting 'default' values to the 'Product' properties. This will remove the need to do them in the constructor. Next, if you wanted to automatically set the class's properties, you can use reflection.

    public class Product
    {
        public int Id { get; set; } = -1;
        public List<ProductLink> Product_Links { get; set; } = new List<ProductLink>();
        ....
        public int Visibility { get; set; } = 0;
    
        public Product(IBaseProduct netforumProduct, MagentoClient client)
        {
            var existingMagentoProduct = client.GetProductBySku(netforumProduct.Code);
            if (existingMagentoProduct != null)
            {
                foreach (PropertyInfo property in typeof(Product).GetProperties().Where(p => p.CanWrite))
                {
                    property.SetValue(this, property.GetValue(existingMagentoProduct, null), null);
                }
            }
        }   
    }
    

    Though, I would like to point out that you probably shouldn't be using a REST client inside a class constructor, especially to just populate its data (also, you are performing a synchronous operation). It would be cleaner to have another layer that is responsible for populating this class using the client, and then use something like AutoMapper to map the data to it.