c# - 从动态集合创建地图不再有效:无法将 System.String 类型的对象转换为 System.Object)
问题描述
我们正在将遗留代码移植到 dotnet 标准,并面临 [我相信] CsvHelper 2.5.0 net451 中不存在的问题。
问题似乎是 CsvReader 无法解决映射中基础属性的正确 ReturnType 并试图将它们全部映射到 System.Object
我已经设法在您的解决方案中通过单元测试来重现它:
[TestMethod]
public void CanCreateMapsFromDynamicList()
{
var data = new List<string[]>
{
new[] { "Col1", "Col2" },
new[] { "1", "one" },
new[] { "2", "two" }
};
var queue = new Queue<string[]>(data);
var parserMock = new ParserMock(queue);
var csvReader = new CsvReader(parserMock);
csvReader.Configuration.RegisterClassMap<SomeTypeClassMap>();
var records = csvReader.GetRecords<SomeType>().ToList();
Assert.IsNotNull(records);
Assert.AreEqual(2, records.Count);
}
public class SomeTypeClassMap : ClassMap<SomeType>
{
public SomeTypeClassMap()
{
Map(x => x.Id).Ignore();
var t = new SomeType();
foreach (var mapping in t.Mappings)
{
Map(mapping);
}
}
}
public class SomeType
{
public int Id { get; set; }
public string Col1 { get; set; }
public string Col2 { get; set; }
public IEnumerable<Expression<Func<SomeType, dynamic>>> Mappings =>
new List<Expression<Func<SomeType, dynamic>>> {i => i.Col1, i => i.Col2};
}
报错:
测试方法 CsvHelper.Tests.CsvReaderMappingTestsRuslan.CanCreateMapsFromDynamicList 抛出异常:System.InvalidCastException:无法将“CsvHelper.Configuration.MemberMap2 [CsvHelper.Tests.CsvReaderMappingTestsRuslan+SomeType,System.String]”类型的对象转换为“CsvHelper.Configuration.MemberMap2” [CsvHelper.Tests.CsvReaderMappingTestsRuslan+SomeType,System.Object]'。
PS我尝试将“映射”属性更改为静态并获得相同的结果。
解决方案
通过添加此重载方法解决了它:
public virtual MemberMap Map<T>( Expression<Func<T, object>> expression, bool useExistingMap = true )
{
var stack = ReflectionHelper.GetMembers(expression);
if (stack.Count == 0)
{
throw new InvalidOperationException("No members were found in expression '{expression}'.");
}
ClassMap currentClassMap = this;
MemberInfo member;
if (stack.Count > 1)
{
// We need to add a reference map for every sub member.
while (stack.Count > 1)
{
member = stack.Pop();
Type mapType;
var property = member as PropertyInfo;
var field = member as FieldInfo;
if (property != null)
{
mapType = typeof(DefaultClassMap<>).MakeGenericType(property.PropertyType);
}
else if (field != null)
{
mapType = typeof(DefaultClassMap<>).MakeGenericType(field.FieldType);
}
else
{
throw new InvalidOperationException("The given expression was not a property or a field.");
}
var referenceMap = currentClassMap.References(mapType, member);
currentClassMap = referenceMap.Data.Mapping;
}
}
// Add the member map to the last reference map.
member = stack.Pop();
return currentClassMap.Map( typeof(TClass), member, useExistingMap );
}
推荐阅读
- aws-lambda - 从 CI/CD 管道部署单个 Lambda 函数
- android - 通过电话和 Firebase ID 连接
- amazon-s3 - 创建 React 应用程序 - 路由器路径不服务于 javascript
- c# - 在 C# 中处理大型表单级对象的正确和最快方法
- r - DT with Shiny:多页可编辑数据表在编辑后跳转到第一页
- zedgraph - ZedGraph 是否提供任何类型的细节层次剔除行为?
- c# - 如何确定一周/一个月的开始日和结束日?
- elixir - 使用 Ecto 将项目添加到多对多关联
- python-3.x - Use a Python dictionary as a lookup table to output new values
- constraint-programming - 使用 Java 计算在区间中找到的变量的值