简体   繁体   English

AutoFixture:解析 IEnumerable<t> ,无法将“ConvertedEnumerable”类型的 object 转换为列表</t>

[英]AutoFixture: resolving IEnumerable<T>, Unable to cast object of type 'ConvertedEnumerable` to List

I tried to use AutoFixture to generate test data for classes that have IEnumerable members.我尝试使用 AutoFixture 为具有 IEnumerable 成员的类生成测试数据。

AutoFixture test code: AutoFixture测试代码:

var fixture = new Fixture();
fixture.Customize<NotificationDto>(c => c.Without(r => r.IntegrationModel));
NotificationDto notificationDto = fixture.Create<NotificationDto>();

Class: Class:

public class NotificationDto 
{
    public NotificationDto() 
    {
        To = new List<RecipientDto>();
    }
    public Guid Id { get; set; }
    public IIntegrationEventModel IntegrationModel { get; set; }
    public IEnumerable<RecipientDto> To { get; set; }
}

During debugging of code代码调试期间在此处输入图像描述

 public CreateNotificationCommand(NotificationDto notificationDto)
    {
        ...
        To = (List<RecipientDto>)(notificationDto.To ?? new List<RecipientDto>());
    }

Getting below error:出现以下错误:

 UpdateNotificationFromAwsSnsCommandHandlers_UpdateNotificationToSuccess
   Duration: 8.9 sec

  Message: 
    System.InvalidCastException : Unable to cast object of type 'ConvertedEnumerable`1[Notification.Core.Notification.Dto.SolrDto.RecipientSolrDto]' to type 'System.Collections.Generic.List`1[Notification.Core.Notification.Dto.SolrDto.RecipientSolrDto]'.

  Stack Trace: 
    CreateNotificationCommand.ctor(NotificationDto notificationDto) line 31
    UpdateNotificationFromAwsSnsCommandHandlersTester.SetAutoData_UpdateNotificationFromAwsSnsCommandHandlers_UpdateNotificationToNotDelivered() line 60
    UpdateNotificationFromAwsSnsCommandHandlersTester.UpdateNotificationFromAwsSnsCommandHandlers_UpdateNotificationToSuccess() line 75
    GenericAdapter`1.GetResult()
    AsyncToSyncAdapter.Await(Func`1 invoke)
    TestMethodCommand.RunTestMethod(TestExecutionContext context)
    TestMethodCommand.Execute(TestExecutionContext context)
    c__DisplayClass1_0.b__0()
    BeforeAndAfterTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action)
 

Please help me?请帮我?

To is an IEnumerable , so it is not guaranteed to be a List , so this cast is not guaranteed to work (in your unit test AutoFixture does not create a list, for example). To是一个IEnumerable ,所以它不能保证是一个List ,所以这个演员不能保证工作(例如,在你的单元测试中,AutoFixture 不会创建一个列表)。 You can change your code to:您可以将代码更改为:

To = notificationDto.To ?? Enumerable.Empty<RecipientDto>();

or something like:或类似的东西:

To = notificationDto.To as List<RecipientDto> 
    ?? notificationDto.To?.ToList() 
    ?? new List<RecipientDto>();

Or change the signature of To to List<RecipientDto> .或者将To的签名更改为List<RecipientDto>

The exception is thrown because notificationDto.To isn't necessarily List<RecipientDto> at runtime, it can be an array of RecipientDto or any other type implicitly casted to IEnumerable<RecipientDto> .抛出异常是因为notificationDto.To在运行时不一定是List<RecipientDto> ,它可以是RecipientDto的数组或隐式转换为IEnumerable<RecipientDto>的任何其他类型。 Hence, when notificationDto.To has different runtime type from List<RecipientDto> the InvalidCastException is thrown.因此,当notificationDto.To具有与List<RecipientDto>不同的运行时类型时,将抛出InvalidCastException

To fix this you can either just remove casting to the list and everything should work fine or have Enumerable.Empty<RecipientDto>() on the right side of the operator ( for both only if To on the right side of = is IEnumerable<RecipientDto> ):要解决此问题,您可以只删除对列表的强制转换,一切都应该正常工作,或者在运算符的右侧使用Enumerable.Empty<RecipientDto>()只有当=右侧的ToIEnumerable<RecipientDto> ):

1. To = notificationDto.To ?? new List<RecipientDto>();
2. To = notificationDto.To ?? Enumerable.Empty<RecipientDto>();

The first approach works because the result type of the expression in this case will be IEnumerable<RecipientDto> .第一种方法有效,因为在这种情况下表达式的结果类型将是IEnumerable<RecipientDto> This follows from the specification for the operator ??这遵循操作员规范?? https://learn.microsoft.com/en-us/do.net/csharp/language-reference/language-specification/expressions#1114-the-null-coalescing-operator . https://learn.microsoft.com/en-us/do.net/csharp/language-reference/language-specification/expressions#1114-the-null-coalescing-operator

We're interested in this part of the spec:我们对规范的这一部分感兴趣:

if A is not a nullable type ( but a reference type ) and an implicit conversion exists from b to A , the result type is A .如果A不是可空类型(而是引用类型)并且存在从bA的隐式转换,则结果类型为A At run-time, a is first evaluated.在运行时,首先评估a If a is not null , a becomes the result.如果a不是null ,则a成为结果。 Otherwise, b is evaluated and converted to type A , and this becomes the result.`否则, b被评估并转换为类型A ,这成为结果。

Where A is the type of a .其中Aa的类型。

In your case a is notificationDto.To and b is new List<RecipientDto>() , therefore A is IEnumerable<RecipientDto> .在您的情况下, anotificationDto.To并且bnew List<RecipientDto>() ,因此AIEnumerable<RecipientDto> Since IEnumerable<RecipientDto> is not a nullable type and there is a conversion from new List<RecipientDto> to IEnumerable<RecipientDto> the result type of the expression will be also IEnumerable<RecipientDto> .由于IEnumerable<RecipientDto>不是可空类型,并且存在从new List<RecipientDto>IEnumerable<RecipientDto>的转换,因此表达式的结果类型也将是IEnumerable<RecipientDto> Hence if To is already IEnumerable<RecipientDto> you don't need to do any casting.因此,如果To已经是IEnumerable<RecipientDto>你不需要做任何转换。

演员收到 object 到列表<object>或 IEnumerable<object><div id="text_translate"><p> 我正在尝试执行以下演员</p><pre>private void MyMethod(object myObject) { if(myObject is IEnumerable) { List&lt;object&gt; collection = (List&lt;object&gt;)myObject; ... do something } else {... do something } }</pre><p> 但我总是以以下异常结束:</p><p> 无法将“System.Collections.Generic.List 1[MySpecificType]' to type 'System.Collections.Generic.List</p><p> 我真的需要这个工作,因为这个方法需要非常通用才能接收单个对象和 collections 两种未指定的类型。</p><p> 这是可能的,还是有另一种方法可以做到这一点。</p><p> 谢谢你。</p></div></object></object> - Cast received object to a List<object> or IEnumerable<object>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法转换对象以键入类型为ienumerable的查询 - unable to cast object to type query of type ienumerable 无法将IEnumerable转换为指定的类型 - Unable to cast IEnumerable to specified type 投IEnumerable <object> 列表 <object> - Cast IEnumerable<object> to List<object> 如何投射IEnumerable <object> 到一个IEnumerable <runtime type> - How to cast an IEnumerable<object> to an IEnumerable<runtime type> 演员表 <object> 到IEnumerable <T> 一般任务中 - Cast List<object> to IEnumerable<T> within Generic Task 将IEnumerable <T>转换为运行时类型 - Cast IEnumerable<T> to runtime type AutoFixture IEnumerable<t> CreateMany() 的行为</t> - AutoFixture IEnumerable<T> behavior with CreateMany() 演员收到 object 到列表<object>或 IEnumerable<object><div id="text_translate"><p> 我正在尝试执行以下演员</p><pre>private void MyMethod(object myObject) { if(myObject is IEnumerable) { List&lt;object&gt; collection = (List&lt;object&gt;)myObject; ... do something } else {... do something } }</pre><p> 但我总是以以下异常结束:</p><p> 无法将“System.Collections.Generic.List 1[MySpecificType]' to type 'System.Collections.Generic.List</p><p> 我真的需要这个工作,因为这个方法需要非常通用才能接收单个对象和 collections 两种未指定的类型。</p><p> 这是可能的,还是有另一种方法可以做到这一点。</p><p> 谢谢你。</p></div></object></object> - Cast received object to a List<object> or IEnumerable<object> 无法使用 LiteDB 将“自定义类型”类型的 object 转换为“System.Collections.IEnumerable”类型 - Unable to cast object of type “custom type” to type 'System.Collections.IEnumerable' Using LiteDB 无法将类型为“ System.Collections.ArrayList”的对象转换为类型为“ System.Collections.Generic.IEnumerable” - Unable to cast object of type 'System.Collections.ArrayList' to type 'System.Collections.Generic.IEnumerable'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM