gpt4 book ai didi

c# - AutoMapper 5 自定义值解析器 "Cannot convert expression type X to return type Y"

转载 作者:行者123 更新时间:2023-11-30 14:48:15 25 4
gpt4 key购买 nike

我从旧版本的 AutoMapper 升级并转换了我的自定义解析器,但我遇到了困难。

public class ProductMappingProfile : Profile
{
public ProductMappingProfile()
{
CreateMap<Product, ProductViewModel>()
.ForMember(
dest => dest.Model,
opt => opt.ResolveUsing<ModelNameResolver>(src => src.ModelId));
// won't compile
}
}

Product 哪里有 int? ModelId 属性和 ProductViewModel 有一个 string Name 属性。

自定义解析器

public class ModelNameResolver : IValueResolver<short?, string, string>
{
private readonly InventoryService _inventoryService;
public ModelNameResolver(InventoryService inventoryService)
{
_inventoryService = inventoryService;
}

public string Resolve(short? source, string destination, string destMember, ResolutionContext context)
{
if (!source.HasValue)
return "n/a";

return _inventoryService.GetModel(source.Value)
.Name;
}
}

编译错误:

The type 'MyNamespace.Web.Resolvers.ModelCodeResolver' cannot be used as type parameter 'TValueResolver' in the generic type or method `'AutoMapper.IMemberConfigurationExpression<TSource,TDestination,TMember>.ResolveUsing<TValueResolver>()'`.

There is no implicit reference conversion from `'MyNamespace.Web.Resolvers.ModelCodeResolver'` to `'AutoMapper.IValueResolver<Data.Models.Product,Web.ViewModels.ProductViewModel,string>'`.

我做错了什么?我怀疑我误解了新的自定义解析器界面。

最佳答案

IValueResolver 接口(interface)应使用源对象类型目标对象类型目标成员类型(应该是 Resolve 方法的类型)进行参数化结果)。在您的情况下,参数应该是

 IValueResolver<Product, ProductViewModel, string>

但是您正在创建参数化的解析器

 IValueResolver<short?, string, string>

short? 不是您的源对象类型

string 不是您的目标对象类型

你应该使用类似的东西:

public class ModelNameResolver : IValueResolver<Product, ProductViewModel, string>
{
private readonly InventoryService _inventoryService;
public ModelNameResolver(InventoryService inventoryService)
{
_inventoryService = inventoryService;
}

public string Resolve(Product source, ProductViewModel destination,
string destMember, ResolutionContext context)
{
var modelId = source.ModelId;
if (!modelId.HasValue)
return "n/a";

return _inventoryService.GetModel(modelId.Value).Name;
}
}

你的映射应该是这样的

var inventoryService = new InventoryService();
var modelNameResolver = new ModelNameResolver(inventoryService);

Mapper.Initialize(c =>
{
c.CreateMap<Product, ProductViewModel>()
.ForMember(dest => dest.Model, opt => opt.ResolveUsing(modelNameResolver));
});

当然,您可以向您的 IoC 容器询问模型名称解析器的实例。


更新:如果您希望解析器可在不同的源数据类型和目标数据类型之间重复使用,那么您有两个选择:

如果您的解析器可以有无参数构造函数,那么您可以使用 IMemberValueResolver:

public class ModelNameResolver : IMemberValueResolver<object, object, int?, string>
{
// create or assign _inventoryService
// also note objects as source and destination
public string Resolve(object source, object destination,
int? sourceMember, string destMember,
ResolutionContext context)
{
if (!sourceMember.HasValue)
return "n/a";

return _inventoryService.GetModel(sourceMember.Value).Name;
}
}

用法

.ForMember(dest => dest.Model, 
opt => opt.ResolveUsing<ModelNameResolver, int?>(src => src.ModelId)

第二个选项 - 不使用解析器。只需将 MapFrom 与执行映射的自定义类一起使用:

.ForMember(dest => dest.Model, 
opt => opt.MapFrom(src => someClass.GetModelName(src.ModelId)));

someSlass 应该包含通过 id 获取模型名称的方法

public string GetModelName(int? modelId)
{
if (!modelId.HasValue)
return "n/a";

return _inventoryService.GetModel(modelId.Value).Name;
}

关于c# - AutoMapper 5 自定义值解析器 "Cannot convert expression type X to return type Y",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42254720/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com