EmitMapper -从抽象模型对象到抽象DTO的通用映射
本文关键字:抽象 映射 DTO 对象 模型 EmitMapper | 更新日期: 2023-09-27 18:06:00
我需要一些帮助从valueinjector过渡到EmitMapper(我决定这样做是出于性能原因)。我的用例是最常见的用例之一:基于一些规则将一个Model对象映射到一个DTO。
其中一条规则是:如果一个属性的类型是DomainObject的子类,那么它应该被映射到它对应的DTO。具体类型没问题,但我也希望它能处理抽象类型。问题是,我不知道如何告诉EmitMapper应该使用哪个DTO,以一种动态的方式。valueinjector代码:
public bool IsDomainObjectAndTargetIsDto(ConventionInfo it)
{
return it.SourceProp.Value.IsNotNull()
&& typeof(DomainObject).IsAssignableFrom(it.SourceProp.Type)
&& it.TargetProp.Type.Name.EndsWith("DTO");
}
由于我所有的dto都实现了DTO<>
接口,我认为我可以使用EmitMapper的DefaultMapConfig.ConvertGeneric
方法,但我就是不知道如何使用。
为了完整起见,我包含了我当前的(不工作的)代码:
public class ModelToDtoConventions()
{
public IMappingConfigurator GetConfig()
{
return new DefaultMapConfig()
.ConvertUsing<IdentificableObject, int>(o => o.Id)
.ConvertGeneric(
typeof (DomainObject),
typeof (DTO<>),
new DefaultCustomConverterProvider(
typeof (DomainObjectToDtoConverter<>)
)
);
}
}
public class DomainObjectToDtoConverter<TDomainObject>
{
public DTO<TDomainObject> Convert(TDomainObject from, object state)
{
return (DTO<TDomainObject>)this.CreateDtoFor(@from);
}
private object CreateDtoFor(object modelObject)
{
var modelType = modelObject.GetType();
var dtoInterface = typeof(DTO<>).MakeGenericType(modelType);
var dtoType = dtoInterface
.GetConcreteSubtypes()
.Single();
return Activator.CreateInstance(dtoType);
}
}
当我尝试在测试中使用这个映射时,我得到了以下异常
'MyProject.WebApi.Test.Utils.DTOInjectorTest.Abstract_DTO_property_of_DTO_can_be_mapped_from_its_model' failed: System.ArgumentException : Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.
at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure)
at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method)
at EmitMapper.MappingConfiguration.MapConfigBaseImpl.GetGenericConverter(Type from, Type to)
at EmitMapper.MappingConfiguration.MapConfigBaseImpl.FilterOperations(Type from, Type to, IEnumerable`1 operations)
at EmitMapper.MappingConfiguration.DefaultMapConfig.GetMappingOperations(Type from, Type to)
at EmitMapper.EmitBuilders.MappingBuilder.BuildCopyImplMethod()
at EmitMapper.ObjectMapperManager.BuildObjectsMapper(String MapperTypeName, Type from, Type to, IMappingConfigurator mappingConfigurator)
at EmitMapper.ObjectMapperManager.GetMapperInt(Type from, Type to, IMappingConfigurator mappingConfigurator)
at EmitMapper.ObjectMapperManager.GetMapperImpl(Type from, Type to, IMappingConfigurator mappingConfigurator)
at MyProject.WebApi.Adapters.DTOInjector.Transform[TDestination](IMappingConfigurator config, Object source, TDestination destination) in c:'Users'faloi'Documents'GitHub'api'WebApi'Adapters'DTOInjector.cs:line 56
at MyProject.WebApi.Adapters.DTOInjector.CreateDto[TDTO](Object entity) in c:'Users'faloi'Documents'GitHub'api'WebApi'Adapters'DTOInjector.cs:line 47
at MyProject.WebApi.Test.Utils.DTOInjectorTest.Abstract_DTO_property_of_DTO_can_be_mapped_from_its_model() in c:'Users'faloi'Documents'GitHub'api'WebApi.Test'Utils'DTOInjectorTest.cs:line 334 c:'Users'faloi'Documents'GitHub'api'WebApi'Adapters'DTOInjector.cs 56
编辑:这是一个我想映射的对象的例子。
//Domain objects
public class Game
{
public IEnumerable<Map> Maps { get; set; }
public Map MostPlayedMap { get; set; }
public Game()
{
this.Maps = new List<Map>();
}
}
public abstract class Map : DomainObject
{
public string Name { get; set; }
}
public class BombDefuseMap : Map
{
public Player BombHolder { get; set; }
}
public class HostageRescueMap : Map
{
public int QuantityOfHostages { get; set; }
}
//DTOs
public class GameDTO : DTOWithId<Game>
{
public List<MapDTO> Maps { get; set; }
public MapDTO MostPlayedMap { get; set; }
}
public abstract class MapDTO
{
public string Name { get; set; }
}
public class BombDefuseMapDTO : MapDTO, DTO<BombDefuseMap>
{
public int BombHolder { get; set; }
}
public class HostageRescueMapDTO : MapDTO, DTO<HostageRescueMap>
{
public int QuantityOfHostages { get; set; }
}
如果你关心性能,可以看看这个页面:http://valueinjecter.codeplex.com/wikipage?title=SmartConventionInjection
这是一个执行得更好的注射,但你没有得到匹配算法中的值,大多数时候你根本不需要它