使用AutoMapper自定义映射

Bid*_*dou 13 .net c# mapping automapper

我有两个非常简单的对象:

public class CategoryDto
{
    public string Id { get; set; }

    public string MyValueProperty { get; set; }
}

public class Category
{
    public string Id { get; set; }

    [MapTo("MyValueProperty")]
    public string Key { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

使用AutoMapper Category将a 映射到a CategoryDto时,我想要以下行为:

除了具有该MapTo属性的属性之外,应该像往常一样映射属性.在这种情况下,我必须读取Attribute的值来查找target属性.source属性的值用于在destination属性中查找要注入的值(借助字典).一个例子总是好于1000字......

例:

Dictionary<string, string> keys = 
    new Dictionary<string, string> { { "MyKey", "MyValue" } };

Category category = new Category();
category.Id = "3";
category.Key = "MyKey";

CategoryDto result = Map<Category, CategoryDto>(category);
result.Id               // Expected : "3"
result.MyValueProperty  // Expected : "MyValue"
Run Code Online (Sandbox Code Playgroud)

该Key属性被映射到MyValueProperty(通过MapTo属性),并且赋值是"MyValue",因为源属性值是"MyKey",它被映射(通过字典)到"MyValue".

这可以使用AutoMapper吗?我当然需要一个适用于每个对象的解决方案,而不仅仅是Category/CategoryDto.

Bid*_*dou 10

我终于(经过这么多小时!!!!)找到了解决方案.我与社区分享这个; 希望它会帮助别人......

编辑:注意它现在更简单(AutoMapper 5.0+),你可以像我在这篇文章中回答的那样:如何使AutoMapper根据MaxLength属性截断字符串?

public static class Extensions
{
    public static IMappingExpression<TSource, TDestination> MapTo<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
    {
        Type sourceType = typeof(TSource);
        Type destinationType = typeof(TDestination);

        TypeMap existingMaps = Mapper.GetAllTypeMaps().First(b => b.SourceType == sourceType && b.DestinationType == destinationType);
        string[] missingMappings = existingMaps.GetUnmappedPropertyNames();

        if (missingMappings.Any())
        {
            PropertyInfo[] sourceProperties = sourceType.GetProperties();
            foreach (string property in missingMappings)
            {
                foreach (PropertyInfo propertyInfo in sourceProperties)
                {
                    MapToAttribute attr = propertyInfo.GetCustomAttribute<MapToAttribute>();
                    if (attr != null && attr.Name == property)
                    {
                        expression.ForMember(property, opt => opt.ResolveUsing(new MyValueResolve(propertyInfo)));
                    }
                }
            }
        }

        return expression;
    }
}

public class MyValueResolve : IValueResolver
{
    private readonly PropertyInfo pInfo = null;

    public MyValueResolve(PropertyInfo pInfo)
    {
        this.pInfo = pInfo;
    }

    public ResolutionResult Resolve(ResolutionResult source)
    {
        string key = pInfo.GetValue(source.Value) as string;
        string value = dictonary[key];
        return source.New(value);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 很高兴你找到了解决方案.您能否稍微扩展您的答案来解释这种方法并提供一个使用示例? (8认同)