2015-04-03 1 views
1

J'ai une action pour rechercher des personnes dans un contrôleur, il retournera une liste de anonymouse:Impossible de convertir IEnumerable de type anonyme en IEnumerable <dynamic>?

[UnitOfWork] 
[HttpGet, Route("api/Search/People")] 
public virtual IHttpActionResult GetResult(string keyword) 
{ 
    // ... 
    var result = peopleList.Select(x => new 
    { 
     PersonId = x.Id.Value, 
     EmploymentNumber = x.EmploymentNumber, 
     FirstName = x.Name.FirstName, 
     LastName = x.Name.LastName, 
     Email = x.Email 
    }); 
    return Ok(result); 
} 

Ci-dessous est le cas de test de la méthode:

[Test] 
public void ShouldSearchPeople() 
{ 
    // Mocks... 
    var target = new PeopleSearchController(searchRepository, personRepository, new FakePermissionProvider()); 
    // Error here 
    var result = (OkNegotiatedContentResult<IEnumerable<dynamic>>)target.GetResult("Ashley"); 
    Assert.NotNull(peopleList); 
    // Other assert... 
} 

Puis-je obtenir l'erreur comme ci-dessous :

System.InvalidCastException: Unable to cast object of type 
'System.Web.Http.Results.OkNegotiatedContentResult`1[System.Collections.Generic.IEnumerable`1[<>f__AnonymousType1e`5[System.String,System.String,System.String,System.Guid,System.String]]]' 
to type 
'System.Web.Http.Results.OkNegotiatedContentResult`1[System.Collections.Generic.IEnumerable`1[System.Object]]'. 

Il semble IEnumerable avec classe unique ou anonyme sont OK pour un tel converti, mais avec IEnumerable anonyme ne fonctionne.

Comment faire une telle conversion? Merci.

+0

peut-être 'var résultat = target.GetResult (" Ashley ") comme OkNegotiatedContentResult >;' fonctionne pour vous dans votre méthode de test ...? – stefankmitph

+0

@stefankmitph 'result' sera toujours nul. –

Répondre

1

Vous ne pouvez pas utiliser le type paramétré dynamique mais concret pour d'autres types paramétrés. Le problème que votre code souffre est appelé covariance et contravariance. Malheureusement, class ne supporte pas la covariance/contravariance (class est toujours invariant). Solution possible:

var result = ((dynamic)target).GetResult("Ashley"); 
//result is of type OkNegotiatedContentResult<...> 
var content = (IEnumerable<dynamic>)result.Content; 

Depuis IEnumerable est covariant, CAST fonctionnera.

En savoir plus sur covariance et contravariance on MSDN.

+0

Merci, cela fonctionne :-) – xinfli

0

Vous pouvez essayer avec

IHttpActionResult result = target.GetResult("Ashley"); 
IEnumerable<dynamic> content = (IEnumerable<dynamic>)((dynamic)result).Content; 

Vous utilisez dynamic utiliser la propriété .Content qui renverra un IEnumerable<T>, et ensuite utiliser covariance pour le jeter aux IEnumerable<object>/IEnumerable<dynamic> (ils sont équivalents au niveau CLR ... dynamic est une magie faite par le compilateur)

Notez que cela ne fonctionnera pas si le T de OkNegotiatedContentResult est un type de valeur, mais dans votre cas c'est un type de référence, donc il n'y a pas de problèmes.

+1

J'ai aussi le même problème. Votre solution fonctionne pour tester le résultat du retour. Mais que faire si je veux tester si le contrôleur retourne '' '' '' OkNegotiationResult''' ou non? –

+0

Cela devrait fonctionner: Assert.AreEqual (typeof (OkNegotiatedContentResult <>), result.GetType(). GetGenericTypeDefinition()); –