2

我正在访问一个 REST API,它返回 JSON 格式的资源列表:

{
    "products": [
        { ... },
        { ... }
    ]
}

当列表很大(> 50 项)时,响应将被分页,并pagination在返回的 JSON 的根节点中添加一个附加项,如下所示:

{
    "pagination": {
        "results" : 490,
        "page" : 1,
        "page_size" : 50,
        "pages" : 10
    },
    "products": [
        { ... },
        { ... }
    ]
}

为了满足这一点,我有一个PaginatedList看起来像这样的类(可能不是最好的名字):

public class PaginatedList
{
    [JsonProperty("pagination")]
    public Pagination Pagination { get; set; }
}

一个ProductList看起来像这样的类:

public class ProductList : PaginatedList
{
    [JsonProperty("products")]
    public List<Product> Products { get; set; }
}

像这样的Pagination课程:

public class Pagination
{
    [JsonProperty("results")]
    public int Results { get; set; }

    [JsonProperty("page")]
    public int Page { get; set; }

    [JsonProperty("page_size")]
    public int PageSize { get; set; }

    [JsonProperty("pages")]
    public int Pages { get; set; }
}

要检索我的资源,我使用:

public List<Product> GetProducts()
{
    return getResourceAsync<ProductList>(productsResourceName).Result.Products;
}

和:

async Task<T> getResourceListAsync<T>(string resourceName)
    {
    var url = string.Concat(BaseUrl, resourceName);
    var credentials = new NetworkCredential(Username, Password);
    var handler = new HttpClientHandler { Credentials = credentials };

    using (var client = new HttpClient(handler)) {
        var response = await client.GetAsync(url);
        var contentString = await response.Content.ReadAsStringAsync();
        var resource = await JsonConvert.DeserializeObjectAsync<T>(contentString);
        return resource;
    }
}

在方法中添加对分页的支持GetProducts非常容易,但这意味着为每种类型的资源(产品、客户、供应商等)复制非常相似的代码。问题是,我如何获得该getResourceListAsync方法以使其支持分页和非分页列表适用于不同的资源?

4

2 回答 2

1

为了使这种情况成为可能:

// supports both scenarios

            var json = @"{    'products': [        { Id : 1 , Name : 'A' },        { Id : 2 , Name : 'B' }    ] }";

            var results = Helper.ParseFromJsonResult<Product>(json);

            var anotherJson = @"{ 'pagination': {
                                                'results' : 490,
                                                'page' : 1,
                                                'page_size' : 50,
                                                'pages' : 10
                                            },
                                            'products': [
                                                { Id : 1 , Name : 'A' },        { Id : 2 , Name : 'B' } 
                                            ]}";

            var anotherResults = Helper.ParseFromJsonResult<Product>(anotherJson);

您可以使用以下代码:

public static class Helper
    {
        private static readonly PluralizationService _NameService =
            PluralizationService.CreateService(new CultureInfo("en-us"));
        // Provides Plural names [ products for Product ]
        // to determinate the name of the result for example products for Product class

        private static ModuleBuilder _ModuleBuilder;

        static Helper()
        {
            var asmName = new AssemblyName();

            asmName.Name = "MyHelpers";

            AssemblyBuilder asmBuilder = Thread.GetDomain().DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Run);

            _ModuleBuilder = asmBuilder.DefineDynamicModule("MyHelpers");

            // Assembly to put runtime generated classes to that.
        }

        private static readonly IDictionary<Type, Type> _HelpersCache = new Dictionary<Type, Type>();

        public static List<T> ParseFromJsonResult<T>(String json)
        {
            Type resultType = null;

            var entityType = typeof(T);

            var pluralName = _NameService.Pluralize(entityType.Name).ToLowerInvariant();
            // products for Product class

            if (_HelpersCache.ContainsKey(entityType))
            {
                // better performance
                resultType = _HelpersCache[entityType];
            }
            else
            {
                // need another runtime generated class 
                // result :
                /* public class products
                   {
                      public List<Product> products;
                   }
                */

                TypeBuilder resultTypeBuilder = _ModuleBuilder.DefineType(pluralName, TypeAttributes.Public);

                FieldBuilder field = resultTypeBuilder.DefineField(pluralName, typeof(List<T>), FieldAttributes.Public);

                resultType = resultTypeBuilder.CreateType();

                _HelpersCache.Add(entityType, resultType);
            }

            Object result = JsonConvert.DeserializeObject(json, resultType);

            return (List<T>)resultType.GetField(pluralName).GetValue(result); // get products field value
        }
    }

我希望这会有所帮助,如果您需要更多信息,请告诉我

祝你好运

于 2013-09-08T21:26:03.717 回答
0

我看到了你的问题。实际上被困在同一个地方。我最终做的是我想要分页实现的类的接口。当我这样做是为了导出数据时,它被称为 IExportable。这个东西返回一个 PagedResult 并接受一个 IPagedRequest。

所以关键是我在任务中的代码只是使用接口,实际上并不知道最终类型是什么。PagedResult 是具有泛型的类型。希望它有所帮助,试图在没有源代码的情况下从我的头顶写这个。

于 2013-09-08T21:10:09.443 回答