【问题标题】:Could not convert IEnumerable of anonymous type to IEnumerable<dynamic>?无法将匿名类型的 IEnumerable 转换为 IEnumerable<dynamic>?
【发布时间】:2015-04-03 06:41:40
【问题描述】:

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

[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 不起作用。

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

【问题讨论】:

  • 也许 var result = target.GetResult("Ashley") as OkNegotiatedContentResult&lt;IEnumerable&lt;object&gt;&gt;; 在您的测试方法中对您有用...?
  • @stefankmitph result 将始终为空。

标签: c# dynamic anonymous-types


【解决方案1】:

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

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

由于IEnumerable 是协变的,因此该转换将起作用。

更多关于协变和逆变on MSDN.

【讨论】:

    【解决方案2】:

    你可以试试

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

    您使用dynamic 来使用将返回IEnumerable&lt;T&gt; 的属性.Content,然后使用协方差将其强制转换为IEnumerable&lt;object&gt;/IEnumerable&lt;dynamic&gt;(它们在CLR 级别是等效的...@ 987654327@ 是编译器完成的魔法)

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

    【讨论】:

    • 我也有类似的问题。您的解决方案可以测试返回结果。但是如果我想测试控制器是否返回OkNegotiationResult呢?
    • 这应该可以工作:Assert.AreEqual(typeof(OkNegotiatedContentResult), result.GetType().GetGenericTypeDefinition());
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-01
    相关资源
    最近更新 更多