2016-04-07 5 views
0

よく定義されたモデルを使用して、よく定義されたWeb APIにLINQプロバイダーを構築しようとしています。私はこれらのウォークスルーを、次の午前:Web APIのLINQプロバイダーが多くの悲嘆を引き起こしている

単一のオブジェクトや複数のオブジェクトを返すときに、私はそれが動作するようになって苦労しています。私は説明します:

元々、idでクエリを作成した場合、明らかに単一の結果を返していましたが、オブジェクトのコレクションを返すクエリを実行すると例外が発生します。

私はいくつかの変更を加えましたが、オブジェクトのコレクションを返すときにはうまくいきましたが、idでクエリを実行しているときと同じ例外がスローされます。

コード私は現在、それが(複数の結果のために働い)持っているとして、次のとおりです。

カスタムクエリプロバイダ

public override object Execute(Expression expression) 
{ 
    SetSecurityToken(); 

    var elementType = TypeSystem.GetElementType(expression.Type); 
    var elementTypeCollection = typeof (IEnumerable<>).MakeGenericType(elementType); 

    var task = GetResult(expression, elementType); 
    var resultProperty = typeof(Task<>).MakeGenericType(elementTypeCollection).GetProperty("Result"); 

    //WHEN IF FAILS IT DOES SO HERE! 
    var result = resultProperty.GetValue(task); 

    return result; 
} 

private Task GetResult(Expression expression, Type elementType) 
{ 
    var requestUrl = Translate(expression); 

    var method = _httpRequest.GetType().GetMethod("GetHttpRequest").MakeGenericMethod(new[] { elementType }); 
    var task = (Task) method.Invoke(_httpRequest, new object[] { requestUrl, _securityToken, null }); 

    return task; 
} 

私はHttpClientをからの呼び出しをラップするクラスを持っています。

public async Task<IEnumerable<T>> GetHttpRequest<T>(string apiPath, string token, string contentType = null) 
{ 
    using (var client = GetHttpClient(true, contentType)) 
    { 
     var formattedPath = FormatPathWith(apiPath, token); 
     var response = await client.GetAsync(formattedPath); 

     var result = response.IsSuccessStatusCode && contentType == null 
      ? await response.Content.ReadAsAsync<IEnumerable<T>>() 
      : default(IEnumerable<T>); 

     return result; 
    } 
} 

私はすべてのIEnumerableを<>の参照を削除した場合、それは単一のオブジェクトの結果のために働く:Getメソッドは次のようになります。

クエリプロバイダ

public override object Execute(Expression expression) 
{ 
    SetSecurityToken(); 

    var elementType = TypeSystem.GetElementType(expression.Type); 

    var task = GetResult(expression, elementType); 
    var resultProperty = typeof(Task<>).MakeGenericType(elementType).GetProperty("Result"); 

    //WHEN IF FAILS IT DOES SO HERE! 
    var result = resultProperty.GetValue(task); 

    return result; 
} 

private Task GetResult(Expression expression, Type elementType) 
{ 
    var requestUrl = Translate(expression); 

    var method = _httpRequest.GetType().GetMethod("GetHttpRequest").MakeGenericMethod(new[] { elementType }); 
    var task = (Task) method.Invoke(_httpRequest, new object[] { requestUrl, _securityToken, null }); 

    return task; 
} 

そして、HTTPラッパー

public async Task<T> GetHttpRequest<T>(string apiPath, string token, string contentType = null) 
{ 
    using (var client = GetHttpClient(true, contentType)) 
    { 
     var formattedPath = FormatPathWith(apiPath, token); 
     var response = await client.GetAsync(formattedPath); 

     var result = response.IsSuccessStatusCode && contentType == null 
      ? await response.Content.ReadAsAsync<T>() 
      : default(T); 

     return result; 
    } 
} 

どちらの場合にもスローされる例外は次のとおりです:

{ "デシリアライズすることはできませんそれはこのようになります。現在のJSON配列(例:[1,2,3])をタイプ 'LinqProvider.Model.Project'にタイプするにはJSONオブジェクトが必要ですct (例: {\ "name \":\ "value \"})を使用して正しくデシリアライズします。これを修正するには、JSONオブジェクトをJSONオブジェクト(例: {\ "name \":\ "値\"})に変更するか、またはデシリアライズされたタイプを配列に変更するか、コレクションインターフェイスを実装する タイプ(ICollection 、IList) のようなJSON配列から逆シリアル化できるリスト。 JsonArrayAttributeを型に追加して、 に強制的にJSON配列から逆シリアル化することもできます。 "}

私はJSONのシリアル化を処理するためにJSON.Netを使用していますが、属性を変更する必要はないので、それに関連するとは思わないオブジェクトの動作の違いを見るために、もちろん私は間違っている可能性があります。

ありがとうございました。

答えて

0

問題は、オブジェクトがWeb APIから取得する方法をJSONクエリプロバイダに単一のオブジェクトまたはオブジェクトの配列と、この行のいずれかになりますに応じてということですが判明:

var elementType = TypeSystem.GetElementType(expression.Type); 

IEnumerableまたはTのいずれかにハードコードされたオブジェクトの予想されるタイプを示します。

幸いにも翻訳された式(呼び出されるURL)から、私は期待されることができます'id'によって行われる単一のオブジェクトを期待できる、または 'all'、 'search'、 'owned'という単語のいずれかがコレクションが見つかった場合期待される。

だから、最終的な解決策は、このようなものになります。この場合

public override object Execute(Expression expression) 
     { 
      var translatedExpression = Translate(expression); 
      SetAdminSecurityToken(); 

      var elementType = GetElementType(expression); 

      var task = GetResultFrom(elementType, translatedExpression); 
      var resultProperty = typeof(Task<>).MakeGenericType(elementType).GetProperty("Result"); 
      var result = resultProperty.GetValue(task); 

      return GetReturnValue(result, elementType); 
     } 

    private Type GetElementType(Expression expression) 
    { 
     var elementType = TypeSystem.GetElementType(expression.Type); 
     //The IsMultipleResults property on the translator encapsulates the 
     //logic mentioned in the answer description. 
     return _queryTranslator.IsMultipleResults ? typeof(IEnumerable<>).MakeGenericType(elementType) : elementType; 
    } 

     private Task GetResultFrom(Type elementType, string translatedExpression) 
     { 
      var securityToken = _queryTranslator.UseUserToken 
       ? GetSecurityToken(_queryTranslator.UserEmail, _queryTranslator.UserPassword) 
       : _securityToken; 

      var method = _httpRequest.GetType().GetMethod("GetHttpRequest").MakeGenericMethod(new[] { elementType }); 
      var task = (Task)method.Invoke(_httpRequest, new object[] { translatedExpression, securityToken, null }); 

      return task; 
     } 

を私が翻訳したURLにいくつかのキーワードに基づいてタイプを決定することができますが、重要なことは、この限りで決定することができるということです何とか私は単一のTまたはIEnumerableとして期待される型を設定することができます。

これは誰かにとって役に立ちます。

関連する問題