C#Automapper如何使用customresolver中的属性解析

Muk*_*thi 5 c# automapper

我使用以下映射将我的数据对象映射到viewmodel对象.

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 >());         
    }
}
Run Code Online (Sandbox Code Playgroud)

分析器

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;
}
}
Run Code Online (Sandbox Code Playgroud)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我使用上面的代码使用单独的自定义值解析器向目标属性添加逻辑.不确定这是正确的方法.

i)有更好的方法来实现这一目标吗?

ii)如果我想为自定义解析器构造函数注入一些依赖项,如何使用unity来解决?

谢谢

gre*_*k40 0

据我了解您的问题,您希望利用 a 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 };
    }
}
Run Code Online (Sandbox Code Playgroud)

您需要一个目标属性才能使用opt.ResolveUsing<TypeValueResolver>(). 这意味着,您可以在适当的目标属性可用的情况下建立映射。

因此,目前,让我们将结果包装到适当的容器类型中:

class Container<TType>
{
    public TType Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

并创建一个映射

Mapper.CreateMap<User, Container<UserViewModel>>()
    .ForMember(d => d.Value, c => c.ResolveUsing<TypeValueResolver>());
Run Code Online (Sandbox Code Playgroud)

还有另一个映射

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

还有另一个映射

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...
Run Code Online (Sandbox Code Playgroud)

最后一个映射有点特殊,因为它依赖于嵌套映射,以便通过单独配置的映射规则使用源中的值更新目标。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);
Run Code Online (Sandbox Code Playgroud)

不知道这是否对你有帮助。如果您重新表述您的问题来描述您最初的问题,而不是您怀疑的解决方案,可能会有更好的方法。