首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何开始创建Linq- to -Repository to HttpRequest框架

如何开始创建Linq- to -Repository to HttpRequest框架
EN

Stack Overflow用户
提问于 2014-11-14 01:12:42
回答 1查看 363关注 0票数 1

举个例子,我有一个简单的WebAPi2,它有一个名为ParentsController的单一控制器,它是一个标准的WebAPi2 ApiController。这是样板。

在客户端,我创建了一个Repository基类,并在此基础上创建了一个ParentRepository类。

ApiRequester:

代码语言:javascript
代码运行次数:0
运行
复制
    public class ApiRequester
{
    readonly Uri _apiServiceBaseAddress;
    readonly String _apiControllerPath;
    readonly Guid _apiKey;

    public ApiRequester(string apiServiceBaseAddress, string apiControllerPath, Guid apiKey)
    {
        _apiServiceBaseAddress = new Uri(apiServiceBaseAddress);
        _apiControllerPath = apiControllerPath;
        _apiKey = apiKey;
    }
    public async Task<T> Get<T>(string queryParameters)
    {
        using (var client = new HttpClient { BaseAddress = _apiServiceBaseAddress })
        {
            //client.Timeout = TimeSpan.FromSeconds(60);
            client.DefaultRequestHeaders.Add("X-APIKey", _apiKey.ToString());

            var response = await client.GetAsync(_apiControllerPath + queryParameters);

            var result = await response.Content.ReadAsAsync<T>();

            return result;
        }
    }

    public async Task<T> Post<T>(string queryParameters, T entity)
    {
        using (var client = new HttpClient { BaseAddress = _apiServiceBaseAddress })
        {
            client.DefaultRequestHeaders.Add("X-APIKey", _apiKey.ToString());
            HttpResponseMessage response = null;

            response = await client.PostAsJsonAsync<T>(_apiControllerPath + queryParameters, entity);

            response.EnsureSuccessStatusCode();
            var result = await response.Content.ReadAsAsync<T>();
            return result;
        }
    }

    public async Task<T> Put<T>(string queryParameters, T entity)
    {
        using (var client = new HttpClient { BaseAddress = _apiServiceBaseAddress })
        {
            client.DefaultRequestHeaders.Add("X-APIKey", _apiKey.ToString());
            var response = await client.PutAsJsonAsync<T>(_apiControllerPath + queryParameters, entity);
            response.EnsureSuccessStatusCode();

            var result = await response.Content.ReadAsAsync<T>();

            return result;
        }
    }

    public async Task Delete(string queryParameters)
    {
        using (var client = new HttpClient { BaseAddress = _apiServiceBaseAddress })
        {
            client.DefaultRequestHeaders.Add("X-APIKey", _apiKey.ToString());

            var response = await client.DeleteAsync(_apiControllerPath + queryParameters);
            response.EnsureSuccessStatusCode();
        }
    }
}

RepositoryBase:

代码语言:javascript
代码运行次数:0
运行
复制
public abstract class RepositoryBase<T> where T : class, IEntity
{
    readonly ApiRequester _requester;

    protected RepositoryBase(string apiBaseUri, string controllerPath, Guid apiKey)
    {
        if (String.IsNullOrWhiteSpace(apiBaseUri))
            throw new ArgumentNullException("apiBaseUri");

        if (apiKey.Equals(default(Guid)))
            throw new ArgumentNullException("apiKey");

        _requester = new ApiRequester(apiBaseUri, controllerPath, apiKey);
    }
    public virtual Task<ICollection<T>> GetAsync(string queryParameters)
    {
        return _requester.Get<ICollection<T>>(queryParameters);
    }

    public virtual Task<T> PostAsync(string queryParameters, T entity)
    {
        return _requester.Post<T>(queryParameters, entity);
    }

    public virtual Task<T> PutAsync(string queryParameters, T entity)
    {
        return _requester.Put<T>(queryParameters, entity);
    }
    public virtual Task DeleteAsync(string queryParameters)
    {
        return _requester.Delete(queryParameters);
    }
}

ParentRepository:

代码语言:javascript
代码运行次数:0
运行
复制
    public class ParentRepository : RepositoryBase<Parent>
{
    public ChannelRepository(string apiBaseUri, string controllerPath, Guid apiKey)
        : base(apiBaseUri, controllerPath, apiKey)
    { }
}

因此,客户端的消费者可以进行调用,从API获取父级列表,如下所示:

代码语言:javascript
代码运行次数:0
运行
复制
pRepo = new ParentRepository();
var parents = await pRepo.GetAsync();

// Do something with parent collection.

父实体如下所示:

代码语言:javascript
代码运行次数:0
运行
复制
public class Parent : IEntity
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid ParentId { get; set; }

    public String Name { get; set; }

// Navigation Properties
    public virtual ICollection<Child> Children { get; set; }
}

我希望在我的存储库方法上允许类似于以下内容:

代码语言:javascript
代码运行次数:0
运行
复制
pRepo = new ParentRepository();
var parents = await pRepo.GetAsync().Where(p => p.Name == "aName").Include(p => p.Children);

这就是我被卡住的地方。

我如何在我的GetAsync()方法中拦截它,以便构建我的http请求?

要获取“Where”子句,我需要创建一个扩展方法吗?类似于:

代码语言:javascript
代码运行次数:0
运行
复制
public static ICollection<TEntity> Where(this ICollection<TEntity> source, Func<TEntity> , bool> predicate)
{
// Do something or not?
}

但是然后呢?

对于'Include‘部分,我在这里需要什么,也许是从System.Reflection获取子集合属性名的东西?

同样,我如何拦截GetAsync()方法中的推断?

我知道可能有更简单的方法可以用重载方法做我想要的事情,但我喜欢创建一个类似linq的方法的想法。

编辑:

为了清楚我想要什么,我认为我需要使用表达式树(还不确定如何)来将我的linq表达式转换为web uri:

因此,在我的客户端中,我写道:var parents = await pRepo.GetAsync().Where(p => p.Name == "aName").Include(p => p.Children);

然后该表达式被转换为如下形式:

代码语言:javascript
代码运行次数:0
运行
复制
GET /api/parents/?name=aName&IncludeChildren=true

然后,客户端可以执行Get请求。注意,这应该是我可以在我构建的任何客户端中使用的东西,目标是任何类型的基于web的应用程序接口,不一定需要是WebAPI。

EN

回答 1

Stack Overflow用户

发布于 2014-11-14 11:39:53

根据我(有限的)经验,Web API控制器有一些可选参数,用于过滤和排序,然后将这些参数转换为对数据访问层中的Repository类的类似linq的请求。其中没有一个驻留在客户端上,客户端正在使用查询字符串中的标准HTTP约定向Web API控制器发出请求,例如:

代码语言:javascript
代码运行次数:0
运行
复制
GET /api/parent?minimumId=5&maximumId=20&orderBy=Name

可选的查询字符串参数可以转换为Linq或Dynamic Linq,以查询底层DAL提供的某种IQueryable。

您可能不会经常在对Web API控制器的请求中看到类似linq的行为,因为控制器本质上是面向HTTP的,而倾向于类似HTTP的行为。

如果你真的想用类似Linq的语法包装对Web API控制器的调用,我会考虑使用Dynamic Linq将你的数据(Funcs/Expression/String/等)转换成Linq查询,因为它至少让你自己避免了对反射的大惊小怪。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26914529

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档