Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 需要映射成员和构造函数的自动映射_C#_Automapper - Fatal编程技术网

C# 需要映射成员和构造函数的自动映射

C# 需要映射成员和构造函数的自动映射,c#,automapper,C#,Automapper,我对AutoMapper是一个全新的人,我只是想了解一下做事情的最佳方式 我很快就遇到了一个棘手的问题:两个简单但真实的对象模型之间的映射。第一个是服务层: public sealed class GeoLocation { public GeoLocation( double latitude, double longitude) { this.Latitude = latitude; this.Longitude

我对AutoMapper是一个全新的人,我只是想了解一下做事情的最佳方式

我很快就遇到了一个棘手的问题:两个简单但真实的对象模型之间的映射。第一个是服务层:

public sealed class GeoLocation
{
    public GeoLocation(
        double latitude,
        double longitude)
    {
        this.Latitude = latitude;
        this.Longitude = longitude;
    }

    public double Latitude { get; private set; }

    public double Longitude { get; private set; }
}

public sealed class Location
{
    public Location(
        string name,
        GeoLocation geoLocation)
    {
        this.Name = name;
        this.GeoLocation = geoLocation;
    }

    public string Name { get; private set; }

    public GeoLocation GeoLocation { get; private set; }
}
第二个是上述数据库层的简化表示:

public sealed class LocationEntity
{
    public LocationEntity(
        string name,
        double latitude,
        double longitude)
    {
        this.Name = name;
        this.Latitude = latitude;
        this.Longitude = longitude;
    }

    public string Name { get; }

    public double Latitude { get; }

    public double Longitude { get; }
}
如果我尝试使用一个简单的
CreateMap().ReverseMap()
调用映射类型,那么在验证映射时会出现问题:

AutoMapperConfigurationException: 
Unmapped members were found. Review the types and members below.
Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
For no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters
===============================================
Location -> LocationEntity (Destination member list)
UserQuery+Location -> UserQuery+LocationEntity (Destination member list)

No available constructor.
===============================================
LocationEntity -> Location (Destination member list)
UserQuery+LocationEntity -> UserQuery+Location (Destination member list)

Unmapped properties:
GeoLocation
No available constructor.
很公平。我不想映射每个构造函数参数,所以我尝试调用
ConstructUsing

Mapper.Initialize(
    config =>
    {
        config
            .CreateMap<Location, LocationEntity>()
            .ConstructUsing((source, _) => new LocationEntity(source.Name, source.GeoLocation?.Latitude ?? 0.0, source.GeoLocation?.Longitude ?? 0));
        config
            .CreateMap<LocationEntity, Location>()
            .ConstructUsing((source, _) => new Location(source.Name, new GeoLocation(source.Latitude, source.Longitude)));
    });
不确定还有什么要做的,我添加了一个
ForMember
调用到
LocationEntity
->
Location
映射:

AutoMapperConfigurationException: 
Unmapped members were found. Review the types and members below.
Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
For no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters
===============================================
LocationEntity -> Location (Destination member list)
UserQuery+LocationEntity -> UserQuery+Location (Destination member list)

Unmapped properties:
GeoLocation
config
    .CreateMap<LocationEntity, Location>()
    .ConstructUsing((source, _) => new Location(source.Name, new GeoLocation(source.Latitude, source.Longitude)))
    .ForMember(
        x => x.GeoLocation,
        options => options.MapFrom((source, target, _, context) => new GeoLocation(source.Latitude, source.Longitude)));
config
.CreateMap()文件
.ConstructUsing((source,)=>新位置(source.Name,新地理位置(source.Latitude,source.Longitude)))
福门博先生(
x=>x.地理位置,
options=>options.MapFrom((源、目标、上下文)=>新地理位置(source.Latitude、source.Longitude));

虽然这解决了问题,但在我看来,我的映射已经变得有些复杂了。我想知道:有没有更好的方法来实现这一点,而不牺牲对象模型的设计?

您的对象模型设计基本上只允许通过构造进行映射(转换),因此无法充分利用AutoMapper的自动和显式映射功能

ConstructUsing
用于选择用于创建目标实例的非默认构造函数,但仍需要成员映射

您需要的是使用
方法的
转换器:

跳过成员映射并使用自定义表达式转换为目标类型

Mapper.Initialize(配置=>
{
config.CreateMap()
.ConvertUsing(source=>newlocationentity(source.Name,source.GeoLocation?纬度0.0,source.GeoLocation?经度0));
config.CreateMap()
.ConvertUsing(source=>新位置(source.Name,新地理位置(source.Latitude,source.Longitude));
});

您的对象模型设计基本上只允许通过构造进行映射(转换),因此无法充分利用AutoMapper的自动和显式映射功能

ConstructUsing
用于选择用于创建目标实例的非默认构造函数,但仍需要成员映射

您需要的是使用
方法的
转换器:

跳过成员映射并使用自定义表达式转换为目标类型

Mapper.Initialize(配置=>
{
config.CreateMap()
.ConvertUsing(source=>newlocationentity(source.Name,source.GeoLocation?纬度0.0,source.GeoLocation?经度0));
config.CreateMap()
.ConvertUsing(source=>新位置(source.Name,新地理位置(source.Latitude,source.Longitude));
});

如果您确实想接管映射,则使用
转换将非常有用。但在这种情况下,更惯用的做法是通过地图来表达。通过向Location添加另一个构造函数(如果需要,可以使用private),您甚至可以删除
ForCtorParam

CreateMap<Location, LocationEntity>().ReverseMap().ForCtorParam("geoLocation", o=>o.MapFrom(s=>s));

class LocationEntity
{
public LocationEntity(string name, double geoLocationLatitude, double geoLocationLongitude)
{
    this.Name = name;
    this.Latitude = geoLocationLatitude;
    this.Longitude = geoLocationLongitude;
}
public string Name { get; }
public double Latitude { get; }
public double Longitude { get; }
}
CreateMap().ReverseMap().ForCtorParam(“地理位置”,o=>o.MapFrom(s=>s));
类位置实体
{
公共位置实体(字符串名称、双地理位置纬度、双地理位置经度)
{
this.Name=Name;
这个。纬度=地理位置纬度;
这个。经度=地理位置经度;
}
公共字符串名称{get;}
公共双纬度{get;}
公共双经度{get;}
}

如果您确实想接管映射,则使用
转换将非常有用。但在这种情况下,更惯用的做法是通过地图来表达。通过向Location添加另一个构造函数(如果需要,可以使用private),您甚至可以删除
ForCtorParam

CreateMap<Location, LocationEntity>().ReverseMap().ForCtorParam("geoLocation", o=>o.MapFrom(s=>s));

class LocationEntity
{
public LocationEntity(string name, double geoLocationLatitude, double geoLocationLongitude)
{
    this.Name = name;
    this.Latitude = geoLocationLatitude;
    this.Longitude = geoLocationLongitude;
}
public string Name { get; }
public double Latitude { get; }
public double Longitude { get; }
}
CreateMap().ReverseMap().ForCtorParam(“地理位置”,o=>o.MapFrom(s=>s));
类位置实体
{
公共位置实体(字符串名称、双地理位置纬度、双地理位置经度)
{
this.Name=Name;
这个。纬度=地理位置纬度;
这个。经度=地理位置经度;
}
公共字符串名称{get;}
公共双纬度{get;}
公共双经度{get;}
}
AM-can-too.AM-can-too。