Reputation: 77
I have an action to search people in a controller, it will return a list of anonymouse:
[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);
}
Below is the test case of the method:
[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...
}
Then I get error as below:
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]]'.
It seems IEnumerable with class or single anonymous are OK for such convert, but IEnumerable with anonymous does not works.
How can I do such conversion? thanks.
Upvotes: 1
Views: 2452
Reputation: 111830
You could try with
IHttpActionResult result = target.GetResult("Ashley");
IEnumerable<dynamic> content = (IEnumerable<dynamic>)((dynamic)result).Content;
You use dynamic
to use the property .Content
that will return a IEnumerable<T>
, and then use covariance to cast it to IEnumerable<object>
/IEnumerable<dynamic>
(they are equivalent at the CLR level... dynamic
is a magic done by the compiler)
Note that this won't work if the T
of OkNegotiatedContentResult
is a value type, but in your case it is a reference type, so there aren't problems.
Upvotes: -1
Reputation:
You are not casting some to dynamic, but concrete parametrized type to other parametrized type. The problem your code is suffering from is called covariance and contravariance. Unfortunately, class
doesn't support covariance/contravariance (class
is always invariant).
Possible workaround:
var result = ((dynamic)target).GetResult("Ashley");
//result is of type OkNegotiatedContentResult<...>
var content = (IEnumerable<dynamic>)result.Content;
Since IEnumerable
is covariant, that cast will work.
More about covariance and contravariance on MSDN.
Upvotes: 2