使用Automapper的Project().To
方法时遇到问题,该方法在执行简单Mapper.Map<>()
时未显示。
我有一个映射到字符串的枚举,以及一个包含该枚举的类,该枚举映射到包含与enum属性同名的字符串属性的另一个类。
当我从一个班级到另一个班级做一个简单的Mapper.Map<>()
时,一切正常。但是当我尝试Project().To()
时,我得到一个例外:
System.ArgumentException: Type 'System.String' does not have a default construct
or
at System.Linq.Expressions.Expression.New(Type type)
at AutoMapper.MappingEngine.CreateMapExpression(Type typeIn, Type typeOut)
at AutoMapper.MappingEngine.CreateMapExpression(Type typeIn, Type typeOut)
at AutoMapper.MappingEngine.<CreateMapExpression>b__9[TSource,TDestination](T
ypePair tp)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Fu
nc`2 valueFactory)
at AutoMapper.MappingEngine.CreateMapExpression[TSource,TDestination]()
at AutoMapper.QueryableExtensions.ProjectionExpression`1.To[TResult]()
at ConsoleApplication1.Program.Main(String[] args)
以下是演示此问题的代码示例:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using AutoMapper.QueryableExtensions;
namespace ConsoleApplication1
{
public static class EnumExtensions
{
public static string DisplayName(this Enum e)
{
var field = e.GetType().GetField(e.ToString());
if (field != null)
{
var display = ((DisplayAttribute[])field.GetCustomAttributes(typeof(DisplayAttribute), false)).FirstOrDefault();
if (display != null)
{
return display.Name;
}
}
return e.ToString();
}
}
public enum Foo
{
[Display(Name = "Thing 1")]
Thing1,
[Display(Name = "Thing 2")]
Thing2
}
public class Bar
{
public Foo SomeFoo { get; set; }
public string Name { get; set; }
}
public class BarViewModel
{
public string SomeFoo { get; set; }
public string Name { get; set; }
}
class Program
{
static void Main(string[] args)
{
try
{
// map from enum value to enum display name
AutoMapper.Mapper.CreateMap<Foo, string>().ConvertUsing(x => x.DisplayName());
AutoMapper.Mapper.CreateMap<Bar, BarViewModel>();
AutoMapper.Mapper.AssertConfigurationIsValid();
List<Bar> bars = new List<Bar>();
bars.Add(new Bar() { Name = "Name1", SomeFoo = Foo.Thing2 });
bars.Add(new Bar() { Name = "Name2", SomeFoo = Foo.Thing1 });
var barsQuery = (from Bar b in bars
select b).AsQueryable();
// works exactly as expected
var barViewModesls1 = AutoMapper.Mapper.Map<IEnumerable<BarViewModel>>(barsQuery).ToList();
// throws an exception "Type 'System.String' does not have a default constructor"
var barViewModels2 = barsQuery.Project().To<BarViewModel>().ToList();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.WriteLine("press a key to continue");
Console.ReadKey();
}
}
}