无法将IEnumerable的匿名类型转换为IEnumerable <dynamic>?</dynamic>

时间:2015-04-03 06:41:41

标签: 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,
        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与类或单个匿名对于这样的转换是可以的,但IEnumerable与匿名不起作用。

我该如何进行此类转换?感谢。

2 个答案:

答案 0 :(得分:1)

你没有将一些动态的,但具体的参数化类型转换为其他参数化类型。您的代码遇到的问题称为协方差和逆变。遗憾的是,class不支持协方差/逆变(class始终不变)。 可能的解决方法:

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

由于IEnumerable是协变的,因此该演员阵容将起作用。

有关协方差和逆变的更多信息on MSDN.

答案 1 :(得分:0)

您可以尝试使用

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

您使用dynamic来使用将返回.Content的属性IEnumerable<T>,然后使用协方差将其转换为IEnumerable<object> / IEnumerable<dynamic>(他们在CLR级别上是等效的...... dynamic是编译器完成的一项神奇工具)

请注意,如果T的{​​{1}}是值类型,则无效,但在您的情况下,它是引用类型,因此没有问题。