如何为AutoMapper实现自定义命名解析器

时间:2015-10-17 19:15:10

标签: c# automapper

如何使用AutoMapper 映射以下类,而不显式指示所有成员映射

onError

上课:

public class Source
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    ... (huge amount of other properties)
}

使用翻译课程:

public class Destination
{
    public string Imie { get; set; }
    public string Nazwisko { get; set; }
    ... (huge amount of other properties)
}

3 个答案:

答案 0 :(得分:2)

以下是如何做到这一点。

考虑以下方法:

public void CreateMapBasedOnDictionary<TSource, TDestination>(IDictionary<string, string> mapping_dictionary)
{
    var mapping_expression = AutoMapper.Mapper.CreateMap<TSource, TDestination>();

    foreach (var kvp in mapping_dictionary)
    {
        string source_property_name = kvp.Key;
        string destination_property_name = kvp.Value;

        Type member_type = typeof (TSource).GetProperty(source_property_name).PropertyType;

        mapping_expression = mapping_expression.ForMember(destination_property_name, x =>
        {
            typeof (IMemberConfigurationExpression<TSource>)
                .GetMethod("MapFrom", new []{typeof(string)})
                .MakeGenericMethod(member_type)
                .Invoke(x, new[] { source_property_name });
        });
    }
}

然后你可以像这样使用它:

var translations = new Dictionary<string, string>()
{
    {"FirstName", "Imie"},
    {"LastName", "Nazwisko"},

};

CreateMapBasedOnDictionary<Source, Destination>(translations);

Source src = new Source()
{
    FirstName = "My first name",
    LastName = "My last name"
};

var dst = AutoMapper.Mapper.Map<Destination>(src);

以下是CreateMapBasedOnDictionary方法的解释:

AutoMapper已经超载ForMember,允许您按名称指定目标属性。我们在这里很好。

它还具有MapFrom的重载,允许您按名称指定源属性。但是,此重载的问题是它需要属性类型的通用参数(TMember)。

我们可以通过使用反射来获取属性的类型,然后使用适当的MapFrom类型参数动态调用TMember方法来解决此问题。

答案 1 :(得分:0)

一种方法是使用Reflection

$scope.showModal = function(param) {
    ngDialog.open({
        template: 'app/biography/bioModal' + param + ".html",
        className: 'ngdialog-theme-plain',
        showClose: true,
        scope: $scope
    });
};

你会这样称呼:

private TDestination Map<TSource, TDestination>(TSource source, Dictionary<string, string> mapData)
        where TSource : class
        where TDestination : class, new()
{
    if (source == null) return null;
    if (mapData == null) mapData = new Dictionary<string, string>();

    TDestination destination = new TDestination();
    PropertyInfo[] sourceProperties = typeof(TSource).GetProperties();
    foreach (PropertyInfo property in sourceProperties)
    {
        string destPropertyName = mapData.ContainsKey(property.Name) ? mapData[property.Name] : property.Name;
        PropertyInfo destProperty = typeof(TDestination).GetProperty(destPropertyName);
        if (destProperty == null) continue;
        destProperty.SetValue(destination, property.GetValue(source));
    }
    return destination;
}

答案 2 :(得分:0)

感谢@ yacoub-massad回答,我已经提出了这个解决方案:

var map = Mapper.CreateMap<Source, Destination>();

var sourceProperties = typeof(Source).GetProperties();
foreach (var sourceProperty in sourceProperties)
{
    var sourcePropertyName = sourceProperty.Name;
    var destinationPropertyName = translations[sourceProperty.Name];

    map.ForMember(destinationPropertyName, mo => mo.MapFrom<string>(sourcePropertyName));
}

var src = new Source() { FirstName = "Maciej", LastName = "Lis" };
var dest = Mapper.DynamicMap<Destination>(src);