我不知道如何IValueResolver在新版本的AutoMapper中使用新界面.也许我在以前版本的AutoMapper中使用它们不正确......
我有很多模型类,其中一些是使用sqlmetal从几个数据库服务器上的几个数据库生成的.
其中一些类具有字符串属性,PublicationCode用于标识订阅,商品或发票或其他任何内容所属的发布.
该发布可以存在于两个系统(旧系统和新系统)中的任何一个系统中,因此我在目标模型类上有一个bool属性,用于指示发布是在旧系统还是新系统中.
使用AutoMapper的旧版本(<5?),我使用的ValueResolver<string, bool>,其采取了PublicationCode作为输入参数,并且返回一个bool指示出版物(旧的或新的系统)的位置.
使用AutoMapper的新版本(5+?),这似乎不再可能.新的IValueResolver需要我拥有的源模型和目标模型的每个组合的唯一实现,src.PublicationCode需要将其解析为dst.IsInNewSystem.
我只是试图以错误的方式使用值解析器吗?有没有更好的办法?我想使用解析器的主要原因是我更喜欢将服务注入到构造函数中,而不必DependencyResolver在代码中使用等(我使用的是Autofac).
目前,我通过以下方式使用它:
// Class from Linq-to-SQL, non-related properties removed.
public class FindCustomerServiceSellOffers {
public string PublicationCode { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这是我拥有的几个数据模型类之一,它包含一个PublicationCode属性).此特定类映射到此视图模型:
public class SalesPitchViewModel {
public bool IsInNewSystem { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这两个类的映射定义是(其中expression是IProfileExpression),删除了不相关的映射:
expression.CreateMap<FindCustomerServiceSellOffers, SalesPitchViewModel>()
.ForMember(d => d.IsInNewSystem, o => o.ResolveUsing<PublicationSystemResolver>().FromMember(s => s.PublicationCode));
Run Code Online (Sandbox Code Playgroud)
解析器:
public class PublicationSystemResolver : ValueResolver<string, bool>
{
private readonly PublicationService _publicationService; …Run Code Online (Sandbox Code Playgroud) 我在我的项目中使用Automapper 5.2.0.当我ProjectTo()在代码中使用时获取此错误:
Mapper未初始化.使用适当的配置调用Initialize.如果您正试图通过容器或以其它方式使用映射器实例,请确保您不必静态Mapper.Map方法的任何电话,如果你使用ProjectTo或UseAsDataSource扩展方法,确保你在适当的IConfigurationProvider通实例.
服务代码
public async Task<FreelancerProfileViewModel> GetFreelancerProfile()
{
var id = Guid.Parse(_identity.GetUserId());
var model = await _freelancerProfiles
.AsNoTracking()
.Where(_ => _.User.Id == id)
.ProjectTo<FreelancerProfileViewModel>()
.FirstAsync();
// var viewmodel = _mapper.Map<FreelancerProfileViewModel>(model);
return model;
}
Run Code Online (Sandbox Code Playgroud)
自动映射配置文件
public class FreelancerDashbordProfile : Profile
{
private readonly IIdentity _identity;
public FreelancerDashbordProfile(IIdentity identity)
{
_identity = identity;
var id = Guid.Parse(_identity.GetUserId());
CreateMap<FreelancerProfile, FreelancerProfileViewModel>()
.ForMember(_ => _.DoingProjectCount,
__ => __.MapFrom(_ => _.Projects.Count(project => project.ProjectState == ProjectState.Doing)))
.ForMember(_ => _.EndProjectCount,
__ => __.MapFrom(_ …Run Code Online (Sandbox Code Playgroud) 我试图更新国家实体的嵌套集合(城市).
只是简单的enitities和dto:
// EF Models
public class Country
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<City> Cities { get; set; }
}
public class City
{
public int Id { get; set; }
public string Name { get; set; }
public int CountryId { get; set; }
public int? Population { get; set; }
public virtual Country Country { get; set; }
}
// DTo's
public class CountryData : IDTO …Run Code Online (Sandbox Code Playgroud) 以前当我使用Automapper v3.x时,忽略未映射的属性可以通过简单地添加一个.IgnoreUnmappedProperties()看起来像这样的扩展来完成
public static class AutoMapperExtensions
{
public static IMappingExpression<TSource, TDestination> IgnoreUnmappedProperties<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
var typeMap = Mapper.FindTypeMapFor<TSource, TDestination>();
if (typeMap != null)
{
foreach (var unmappedPropertyName in typeMap.GetUnmappedPropertyNames())
{
expression.ForMember(unmappedPropertyName, opt => opt.Ignore());
}
}
return expression;
}
}
Run Code Online (Sandbox Code Playgroud)
如何重写此扩展以与V5.x一起使用.我当然可以为每个属性添加以下内容.
.ForMember(dest => dest.LastUpdatedBy, opt => opt.Ignore())
Run Code Online (Sandbox Code Playgroud)
或不打电话
Mapper.AssertConfigurationIsValid();
Run Code Online (Sandbox Code Playgroud) 如果在基本数据传输对象的映射中配置了自动映射5.2(当前最新),则忽略ExplicitExpansion()配置.但是,如果直接在Derived DTO中配置了映射,它仍然可以正常工作.我有一对DTO类在字段集和映射配置中包含如此多的重复,我试图将它隔离到公共基础DTO类,但是这个问题阻止了我这样做.
下面的代码说明了这种奇怪的行为.有四个测试,其中两个失败,断言没有扩展基础DTO的属性.如果我将1-1..1-4行移动到2.1,则所有测试都通过.
我是否错过了一些代码或者这是Automapper中的错误,我必须向Automapper的错误跟踪器报告此问题?或者它可能是"按设计",但为什么呢?(Ivan Stoev提出了一个有效的解决方案,但请允许我推迟接受答案,因为我面临的问题不是那么简单,我在下面的更新中添加了更多细节).
UnitTest1.cs:
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace AutoMapperIssue
{
public class Source { public string Name; public string Desc; }
public class DtoBase { public string Name { get; set; } }
public class DtoDerived : DtoBase { public string Desc { get; set; } }
[TestClass] public class UnitTest1
{
[AssemblyInitialize] public static void AssemblyInit(TestContext context)
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<Source, DtoBase>()
.ForMember(dto => dto.Name, conf => { …Run Code Online (Sandbox Code Playgroud) 我有要映射的类,但它们没有默认的构造函数,我不希望它们有.这是因为我只映射到现有对象/从现有对象映射.
public class Order
{
public string OrderName { get; set; }
public Order(string name)
{
this.OrderName = name;
}
}
public class OrderProcessor
{
private IService service;
public string OrderName { get; set; }
public OrderProcessor(IService service)
{
this.service = service;
Mapper.Initialize(config => config.CreateMap<Order, OrderProcessor>());
}
public void Init()
{
var order = this.service.GetOrder();
// this works
Mapper.Map(order, this);
// this fails
Mapper.Configuration.AssertConfigurationIsValid();
}
}
Run Code Online (Sandbox Code Playgroud)
AutoMapper.AutoMapperConfigurationException:找到未映射的成员.查看下面的类型和成员.添加自定义映射表达式,忽略,添加自定义解析程序或修改源/目标类型对于无匹配的构造函数,添加无参数ctor,添加可选参数或映射所有构造函数参数
订单 - > OrderProcessor(目标成员列表)
没有可用的构造函数.
在Tests.cs中的Test():行
当我不想创建新对象时,如何使配置断言传递以及失败的原因?
我最近从 Automapper 4.2.1 升级到 5.1.1,并且在使用涉及开放泛型的先前有效映射时遇到问题。
以前,在 automapper 配置中,我有以下打开的通用映射配置
CreateMap(typeof(IPager<>), typeof(ModelPager<>))
.ForMember("Items", e => e.MapFrom(o => (IEnumerable) o));
Run Code Online (Sandbox Code Playgroud)
这在 Automapper 4 中有效,但在InvalidOperaionException尝试通过IMapper.Map<TDestination>(source). 执行Items ForMember操作的映射时似乎失败,异常消息为“ Sequence contains no matching element ”
这反映在示例实现代码下面
IPager<TSource>器具IEnumerable<TSource>,以及Items财产ModelPager<TDestination>是IEnumerable<TDestination>如此铸造应该是有效的。并且存在每个TSource到的有效映射TDestination
CreateMap<TSource, TDestination>();
Run Code Online (Sandbox Code Playgroud)
网页界面
public interface IPager<out TItem> : IEnumerable<TItem>
{
int CurrentPage { get; }
int PageCount { get; }
int PageSize { get; }
int TotalItems { get; } …Run Code Online (Sandbox Code Playgroud) 我正在尝试向 CastleWindsor 注册 AutoMapper 5.1.1,但我不知道在哪里正确调用 Mapper.Initialize()。
自动映射器简介:
namespace AutoMapper_DI.Mappings
{
public class WebMappingProfile : Profile
{
public WebMappingProfile()
{
CreateMap<Person, PersonDTO>();
}
}
}
Run Code Online (Sandbox Code Playgroud)
温莎城堡注册:
class MainInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IMapper>().UsingFactoryMethod(x =>
{
return new MapperConfiguration(c =>
{
c.AddProfile<WebMappingProfile>();
}).CreateMapper();
}));
container.Register(Component.For<MainClass>());
}
}
Run Code Online (Sandbox Code Playgroud)
然后当我使用 _mapper 时,出现 Mapper 未初始化异常:
class MainClass
{
private readonly IMapper _mapper;
public MainClass(IMapper mapper)
{
_mapper = mapper;
}
public void Start()
{
Person p = new …Run Code Online (Sandbox Code Playgroud) TL;DR:我在使用多态映射时遇到了麻烦。我制作了一个带有测试套件的 github repo 来说明我的问题。请在这里找到它:链接到回购
我正在努力实现保存/加载功能。为了实现这一点,我需要确保我正在序列化的域模型以序列化友好的方式表示。为了实现这一点,我创建了一组 DTO,其中包含执行有意义的保存或加载所需的最低限度的信息集。
域的类似内容:
public interface IDomainType
{
int Prop0 { get; set; }
}
public class DomainType1 : IDomainType
{
public int Prop1 { get; set; }
public int Prop0 { get; set; }
}
public class DomainType2 : IDomainType
{
public int Prop2 { get; set; }
public int Prop0 { get; set; }
}
public class DomainCollection
{
public IEnumerable<IDomainType> Entries { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
...对于 DTO
public interface IDto
{
int …Run Code Online (Sandbox Code Playgroud) 在我只能读取的远程数据库中,每天每小时有 24 列连续。他们的名字是 P1、P2、...、P24。
我必须将这些值复制到我自己的数据库中,我将其命名为 H1、H2、...、H24。
如何使用自动映射器将远程列映射到本地列?
CreateMap<Data.Context.SomeTableFromRemoteDb, Data.Entity.MyTableInLocaldb>()
.ForMember(x => x.H1, y => y.MapFrom(z => z.P1))
.ForMember(x => x.H2, y => y.MapFrom(z => z.P2))
.ForMember(x => x.H3, y => y.MapFrom(z => z.P3))
.ForMember(x => x.H4, y => y.MapFrom(z => z.P4))
.ForMember(x => x.H5, y => y.MapFrom(z => z.P5))
.ForMember(x => x.H6, y => y.MapFrom(z => z.P6))
.ForMember(x => x.H7, y => y.MapFrom(z => z.P7))
.ForMember(x => x.H8, y => y.MapFrom(z => z.P8))
.ForMember(x => x.H9, y => y.MapFrom(z => …Run Code Online (Sandbox Code Playgroud)