nozzlegear / ShopifySharp

ShopifySharp is a .NET library that helps developers easily authenticate with and manage Shopify stores.
https://nozzlegear.com/shopify-development-handbook
MIT License
743 stars 309 forks source link

Generic ListFilter issue #944

Open cappamontana opened 11 months ago

cappamontana commented 11 months ago

Hi,

Honestly this is not an issue but more of a shortcoming or I truly miss something and would appreciate if you could help. At the moment, depending on a user model, we have to gather data from Shopify. For that I've written a generic function so that we don't have to implement the same logics all over again and again basically for all type of endpoint requests.

 public async Task<List<JObject>> getPaginatedData<S>(S service,  ListFilter<CollectionListing> filter)
            where S : ShopifySharp.ICollectionListingService
        {

            var rows = new List<JObject>();
            var page = await service.ListAsync(filter);

            while (true)
            {
                rows.AddRange(page.Items.Select(r => JObject.FromObject(r)).ToList());

                if (!page.HasNextPage) break;

                page = await service.ListAsync(page.GetNextPageFilter());
            }

            return rows;
        }

This function is used in for example:

               case "Orders":
                    OrderService orderService = new OrderService(shop, accessToken);
                    var orderFilter = new OrderListFilter() 
                    {
                        Status = "all",
                        CreatedAtMin = startDate,
                        CreatedAtMax = endDate,
                        Limit = 250
                    };

                    rows = await getPaginatedData((ICollectionListingService)orderService,orderFilter);

                    break;

The issue here is that "orderFilter" can't be converted to a CollectionListing. Is there any other way of doing this?

alonghurst commented 11 months ago

The ICollectionListingService is used to list collections so can't list anything but Collections. There is no base functionality for ListAsync on IShopifyService or the ShopifyService base class, so you can't write a generic method to handle the List request on a service instance.

However you can use a callback function like so (compiles but is untested):

public async Task<List<T>> getPaginatedData<T>(ListFilter<T> filter, Func<ListFilter<T>, Task<ListResult<T>>> listAsync)
{
    var rows = new List<T>();
    var page = await listAsync(filter);

    while (true)
    {
        rows.AddRange(page.Items);

        if (!page.HasNextPage) break;

        page = await listAsync(page.GetNextPageFilter());
    }

    return rows;
}

And used like this:

OrderService orderService = new OrderService(shop, accessToken);
var orderFilter = new OrderListFilter()
{
    Status = "all",
    CreatedAtMin = startDate,
    CreatedAtMax = endDate,
    Limit = 250
};

var orderRows = await getPaginatedData(orderFilter, f => orderService.ListAsync(f));

ProductService productService = new ProductService(shop, accessToken);
var productFilter = new ProductListFilter
{
    Status = "all",
    CreatedAtMin = startDate,
    CreatedAtMax = endDate,
    Limit = 250
};

var productRows = await getPaginatedData(productFilter, f => productService.ListAsync(f));