在从ValueInjecter过渡到EmitMapper时,我需要一些帮助(出于性能原因,我已决定这样做)。我的用例是最常见的用例之一:根据一些规则将模型对象映射到 DTO。
其中一条规则是:如果属性的类型是 DomainObject 的子类,则应将其映射到其对应的 DTO。使用具体类型没关系,但我也希望它与抽象类型一起使用。问题是我不知道如何以动态方式告诉 EmitMapper 应该使用哪个 DTO。
在 ValueInjecter 代码中:
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; }
}