C# 无法将匿名类型的IEnumerable转换为IEnumerable?

C# 无法将匿名类型的IEnumerable转换为IEnumerable?,c#,dynamic,anonymous-types,C#,Dynamic,Anonymous Types,我有一个在控制器中搜索人员的操作,它将返回匿名用户列表: [UnitOfWork] [HttpGet, Route("api/Search/People")] public virtual IHttpActionResult GetResult(string keyword) { // ... var result = peopleList.Select(x => new { PersonId = x.Id.Value, Employ

我有一个在控制器中搜索人员的操作,它将返回匿名用户列表:

[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);
}
以下是该方法的测试用例:

[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...
}
然后我得到如下错误:

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]]'.
似乎IEnumerable with class或single anonymous可以进行这种转换,但IEnumerable with anonymous不起作用


我怎样才能做这样的转换?谢谢。

您并没有将某些参数化类型强制转换为动态类型,而是将具体的参数化类型强制转换为其他参数化类型。代码遇到的问题称为协方差和逆变。不幸的是,类不支持协方差/逆变换,类总是不变的。 可能的解决办法:

var result = ((dynamic)target).GetResult("Ashley");
//result is of type OkNegotiatedContentResult<...>
var content = (IEnumerable<dynamic>)result.Content;
由于IEnumerable是协变的,所以该转换将起作用

有关协方差和逆变换的更多信息

您可以尝试使用

IHttpActionResult result = target.GetResult("Ashley");
IEnumerable<dynamic> content = (IEnumerable<dynamic>)((dynamic)result).Content;
您可以使用dynamic来使用将返回IEnumerable的property.Content,然后使用协方差将其强制转换为IEnumerable/IEnumerable。它们在CLR级别是等效的。。。动态是由编译器完成的一个魔术


请注意,如果OkNegotiatedContentResult的t是一个值类型,这将不起作用,但在您的情况下,它是一个引用类型,因此没有问题。

可能var result=target.GetResultAshley作为OkNegotiatedContentResult;在你的测试方法中对你有效…?@stefankmitph结果将始终为空。我也有类似的问题。您的解决方案用于测试返回结果。但是,如果我想测试控制器是否返回OkNegotiationResult,该怎么办呢?这应该是可行的:Assert.arequalTypeOfOfOfOfOnGottatedContentResult,result.GetType.GetGenericTypeDefinition;