C# 用于请求不同资源的可选分页列表的通用异步方法

C# 用于请求不同资源的可选分页列表的通用异步方法,c#,json,generics,pagination,async-await,C#,Json,Generics,Pagination,Async Await,我正在访问一个REST API,它返回JSON格式的资源列表: { "products": [ { ... }, { ... } ] } 当列表很大(>50项)时,响应将被分页,并向返回的JSON的根节点添加一个额外的pagination项,如下所示: { "pagination": { "results" : 490, "page" : 1, "page_size" : 50,

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

{
    "products": [
        { ... },
        { ... }
    ]
}
当列表很大(>50项)时,响应将被分页,并向返回的JSON的根节点添加一个额外的
pagination
项,如下所示:

{
    "pagination": {
        "results" : 490,
        "page" : 1,
        "page_size" : 50,
        "pages" : 10
    },
    "products": [
        { ... },
        { ... }
    ]
}
public class PaginatedList
{
    [JsonProperty("pagination")]
    public Pagination Pagination { get; set; }
}
public class ProductList : PaginatedList
{
    [JsonProperty("products")]
    public List<Product> Products { get; set; }
}
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; }
}
为了满足这一需求,我有一个
paginedList
类(可能不是最好的名称),它看起来像:

{
    "pagination": {
        "results" : 490,
        "page" : 1,
        "page_size" : 50,
        "pages" : 10
    },
    "products": [
        { ... },
        { ... }
    ]
}
public class PaginatedList
{
    [JsonProperty("pagination")]
    public Pagination Pagination { get; set; }
}
public class ProductList : PaginatedList
{
    [JsonProperty("products")]
    public List<Product> Products { get; set; }
}
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; }
}
一个
ProductList
类,看起来像:

{
    "pagination": {
        "results" : 490,
        "page" : 1,
        "page_size" : 50,
        "pages" : 10
    },
    "products": [
        { ... },
        { ... }
    ]
}
public class PaginatedList
{
    [JsonProperty("pagination")]
    public Pagination Pagination { get; set; }
}
public class ProductList : PaginatedList
{
    [JsonProperty("products")]
    public List<Product> Products { get; set; }
}
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;
}
public List GetProducts()
{
返回getResourceAsync(productsResourceName).Result.Products;
}
以及:

异步任务getResourceListAsync(字符串resourceName) { var url=string.Concat(BaseUrl,resourceName); var凭证=新的网络凭证(用户名、密码); var handler=newhttpclienthandler{Credentials=Credentials}; 使用(var客户端=新的HttpClient(处理程序)){ var response=wait client.GetAsync(url); var contentString=await response.Content.ReadAsStringAsync(); var resource=await JsonConvert.DeserializeObjectAsync(contentString); 返回资源; } }
GetProducts
方法中添加对分页的支持非常简单,但这意味着为每种类型的资源(产品、客户、供应商等)复制非常相似的代码。问题是,如何获得
getResourceListAsync
方法,使其支持分页和非分页列表,并适用于不同的资源?

我看到了您的问题。实际上是被困在同一辆车里。我最终做的是一个接口,我想让我的类实现这个接口。正如我在导出数据时所做的那样,它被称为IExportable。这个东西返回PagedResult并接受IPagedRequest

所以关键是我在任务中的代码只是使用接口,实际上不知道终端类型是什么。PagedResult是具有泛型的类型。
希望它能有所帮助,试着在没有来源的情况下从头开始写这篇文章。

为了使这个场景成为可能:

// 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);
//支持这两种方案
var json=@“{'products':[{Id:1,名称:'A'},{Id:2,名称:'B'}]}”;
var results=Helper.ParseFromJsonResult(json);
var anotherJson=@“{‘分页’:{
“结果”:490,
“页面”:1,
“页面大小”:50,
“页数”:10页
},
“产品”:[
{Id:1,名称:'A'},{Id:2,名称:'B'}
]}";
var anotherResults=Helper.ParseFromJsonResult(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
        }
    }
公共静态类帮助器
{
私有静态只读多元化服务\u名称服务=
CreateService(新文化信息(“en-us”);
//提供复数名称[产品对应产品]
//为Product class确定结果(例如products)的名称
私有静态模块生成器_ModuleBuilder;
静态助手()
{
var asmName=新的AssemblyName();
asmName.Name=“MyHelpers”;
AssemblyBuilder asmBuilder=Thread.GetDomain().DefinedDynamicAssembly(asmName,AssemblyBuilderAccess.Run);
_ModuleBuilder=asmBuilder.DefinedDynamicModule(“MyHelpers”);
//程序集将运行时生成的类放入该程序集。
}
私有静态只读IDictionary_HelpersCache=new Dictionary();
公共静态列表ParseFromJsonResult(字符串json)
{
类型resultType=null;
var entityType=typeof(T);
var pluralName=_NameService.Pluralize(entityType.Name).ToLowerInvariant();
//产品类别的产品
if(_HelpersCache.ContainsKey(entityType))
{
//更好的性能
结果类型=_HelpersCache[entityType];
}
其他的
{
//需要另一个运行时生成的类吗
//结果:
/*公共类产品
{
公开上市产品;
}
*/
TypeBuilder结果TypeBuilder=\u ModuleBuilder.DefineType(pluralName,TypeAttributes.Public);
FieldBuilder field=resultTypeBuilder.DefineField(pluralName、typeof(List)、FieldAttributes.Public);
resultType=resultTypeBuilder.CreateType();
_添加(entityType,resultType);
}
Object result=JsonConvert.DeserializeObject(json,resultType);
return(List)resultType.GetField(pluralName).GetValue(result);//获取产品字段值
}
}
我希望这有帮助,如果你想了解更多信息,请告诉我


祝你好运

为什么要异步等待异步方法?1.这毫无意义,你没有得到异步的任何好处。2.这几乎是在要求死锁发生。另外,你是否已经试图以某种方式解决你的问题?你试了什么?这是怎么失败的?@svick欢迎你用一个精巧的回答来解决你的问题。我刚刚开始使用异步,显然还没有对如何处理它有最好的理解。@svick我有一个基于RestSharp的运行良好的同步解决方案,但将其转换为异步使我完全陷入困境。非常感谢您的建议。请您提供更多详细信息,例如在
GetProducts中添加示例分页