首页 > 解决方案 > C#:默认情况下使 System.Data.Services.Client.DataServiceQuery 异步

问题描述

Mono.Android 要求我进行异步查询。我可以这样做:

DataServiceQuery<T> dataServiceQuery = query as DataServiceQuery<T>;
return (new TaskFactory<IEnumerable<T>>()).FromAsync(dataServiceQuery.BeginExecute(null, null), asyncResult => dataServiceQuery.EndExecute(asyncResult)).Result;

问题是我不想在每次查询时都调用此方法,因为这会强制使用我的库的用户调用该方法,否则 Mono 会崩溃,所以我想让 DataServiceQuery 通过默认。我可以通过覆盖 DataServiceQuery 中的 GetEnumerator() 函数来做到这一点,但它的构造函数是私有的,所以我不允许这样做。我想我剩下的唯一选择是用我的更改重新编译 System.Data.Services.Client.dll。也许 DataServiceContext 有一个技巧,但老实说我没有选择。

谢谢你的帮助,马克西姆

标签: c#androidxamarinmonoodata

解决方案


不可能自动执行此操作,但您可以通过创建一个名为 SelectAsync 的新 Select 函数来使您的语句更好。

事实上,这也解决了 OData 和 LINQ 的问题,因为您必须将 Selects 包装为匿名类型,现在您可以在查询后调用 Select(这需要更长的时间,因为您要查询整个类,但这不是我的问题)。

这是 SelectAsync 扩展方法的代码:

public static IEnumerable<T> SelectAsync<T>(this IQueryable<T> queryable)
{
    return queryable.SelectAsync(x => x);
}

public static IEnumerable<TResult> SelectAsync<T, TResult>(this IQueryable<T> queryable, Function<T, TResult> selector)
{
    var dataServiceQuery = queryable as DataServiceQuery<T>;
    return Task.Run(async () => (await (new TaskFactory<IEnumerable<T>>()).FromAsync(dataServiceQuery.BeginExecute, dataServiceQuery. EndExecute, null)).Select(selector)).Result;
}

在 Mono.Android 中使用 LINQ 执行查询现在更加直观。

var itemNames = Items.Where(item => item.ID == 0).Select(item => item.Name);
var goodCars = Cars.Where(car => car.Fuel >= 0.5);

转换为:

var itemNames = Items.Where(item => item.ID == 0).SelectAsync(item => item.Name);
var goodCars = Cars.Where(car => car.Fuel >= 0.5).SelectAsync();

据我所知,这是最好的,因为 System.Data.Services 目前在 Mono.Android 中不完全支持。这是一个很好且直观的解决方法。

资料来源:


推荐阅读