C# Automapper如何使用自定义解析器中的属性解析?

5
我将使用以下映射方式将我的数据对象映射到视图模型对象中。
ObjectMapper.cs
public static class ObjectMapper
{
    public static void Configure()
    {
        Mapper.CreateMap<User, UserViewModel>()
            .ForMember(dest => dest.Title,
                       opt => opt.ResolveUsing<TitleValueResolver>())
            .ForMember(dest => dest.Name,
                       opt => opt.ResolveUsing<NameValueResolver >())
            .ForMember(dest => dest.ShortName,
                       opt => opt.ResolveUsing<ShortNameValueResolver >());         
    }
}

解析器

public class Parser{
public string GetTitle(string title){
/* add some logic */
return title;
}
public string GetName(string title){
/* add some logic */
return name;
}
public string GetShortName(string title){
/* add some logic */
return shortname;
}
}

AutoMapperCustomResolvers.cs

public class TitleValueResolver : ValueResolver<User, string>
{
    private readonly BaseValueResolver _baseResolver;
    public TitleValueResolver()
    {
        _baseResolver = new BaseValueResolver();
    }

    protected override string ResolveCore(Usersource)
    {
        return _baseResolver.Parser.GetTitle(source.TITLE);
    }
}

public class NameValueResolver : ValueResolver<User, string>
{
    private readonly BaseValueResolver _baseResolver;
    public NameValueResolver()
    {
        _baseResolver = new BaseValueResolver();
    }

    protected override string ResolveCore(Usersource)
    {
        return _baseResolver.Parser.GetName(source.TITLE);
    }
}

public class ShortNameValueResolver : ValueResolver<User, string>
{
    private readonly BaseValueResolver _baseResolver;
    public ShortNameValueResolver()
    {
        _baseResolver = new BaseValueResolver();
    }

    protected override string ResolveCore(Usersource)
    {
        return _baseResolver.Parser.GetShortName(source.TITLE);
    }
}

我使用上述代码,使用单独的自定义值解析器来添加目标属性的逻辑。不确定这是否是正确的方法。
i)有更好的方法吗?
ii)如果我想将一些依赖项注入到自定义解析器构造函数中,如何使用Unity进行解析?
谢谢

你如何期望构造TitleValueResolver?它没有默认构造函数,而且你没有为映射配置提供一个ConstructedBy表达式。一般来说,你的示例严重缺少类...请减少或提供缺失的部分,以将你的示例转换为MVCE。 - grek40
@grek40,我已经更新了我的问题。 - Mukil Deepthi
“TypeValueResolver” 是你的新 “TitleValueResolver” 吗?你期望一个针对 “MAMAsset” 的值解析器如何解析来自 “User” 类型的任何内容? - grek40
抱歉。我更新了我的问题,请看清楚一点。 - Mukil Deepthi
1个回答

0

根据我的理解,您想要利用一个ValueResolver,将多个源属性解析为中间数据对象,然后再用它来解析多个目标属性。例如,我假设以下是源、目标、中间和解析器类型:

// source
class User
{
    public string UserTitle { get; set; }
}

// target
class UserViewModel
{
    public string VM_Title { get; set; }

    public string VM_OtherValue { get; set; }
}

// intermediate from ValueResolver
class UserTitleParserResult
{
    public string TransferTitle { get; set; }
}

class TypeValueResolver : ValueResolver<User, UserTitleParserResult>
{
    protected override UserTitleParserResult ResolveCore(User source)
    {
        return new UserTitleParserResult { TransferTitle = source.UserTitle };
    }
}

为了使用opt.ResolveUsing<TypeValueResolver>(),您需要一个目标属性。这意味着你可以建立映射,其中适当的目标属性是可用的。

所以,暂时将结果包装到适当的容器类型中:

class Container<TType>
{
    public TType Value { get; set; }
}

并创建一个映射

Mapper.CreateMap<User, Container<UserViewModel>>()
    .ForMember(d => d.Value, c => c.ResolveUsing<TypeValueResolver>());

另一个映射

Mapper.CreateMap<UserTitleParserResult, UserViewModel>()
    .ForMember(d => d.VM_Title, c => c.MapFrom(s => s.TransferTitle))
    .ForMember(d => d.VM_OtherValue, c => c.Ignore());

另一个映射

Mapper.CreateMap<User, UserViewModel>()
    .BeforeMap((s, d) =>
    {
        Mapper.Map<User, Container<UserViewModel>>(s, new Container<UserViewModel> { Value = d });
    })
    .ForAllMembers(c => c.Ignore());
// establish more rules for properties...

最后一个映射有点特殊,因为它依赖于嵌套映射,以通过单独配置的映射规则从源更新目标中的值。您可以通过在实际映射类型的BeforeMap中添加适当的中间映射和调用来为不同属性添加多个不同的传输映射。在其他映射中处理的属性需要被忽略,因为AutoMapper不知道BeforeMap中的映射。
小型使用示例:
var user = new User() { UserTitle = "User 1" };

// create by mapping
UserViewModel vm1 = Mapper.Map<UserViewModel>(user);

UserViewModel vm2 = new UserViewModel() { VM_Title = "Title 2", VM_OtherValue = "Value 2" };
// map source properties into existing target
Mapper.Map(user, vm2);

不知道这是否对您有所帮助。如果您重新描述问题以描述初始问题而不是您认为的解决方案,则可能会有更好的方法。

我已经更新了我的问题。希望现在清楚了。 - Mukil Deepthi
抱歉,Unity 超出了我的范围,我还没有使用过它。 - grek40
嗨,基本上我正在尝试使用ValueResolver,它将解析一个单一的源属性到一个中间对象,该对象将解析多个目标属性。 - Mukil Deepthi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接