从外部向AutoMapper类型转换器传递值

19
我有一个多语言数据库,它根据键和枚举Language返回值。当我将DB对象转换为模型时,我希望模型包含基于键和当前语言的翻译值。
键来自DB对象,但我如何将当前语言传递给Mapper.Map()函数?
目前,我使用[ThreadStatic]属性在调用Mapper.Map<>之前设置区域性,并在TypeConverter中检索它。
public enum Language
{
    English, French, Italian, Maltese
}

public class MultilingualValue<T>
{
    public Dictionary<Language, T> Value { get; set; }
    public MultilingualValue()
    {
        this.Value = new Dictionary<Language, T>();
    }
}

public class PersonData
{
    public string FirstName { get; set; }
    public MultilingualValue<string> City { get; set; }
}

public void MapPerson()
{
    PersonData personData = new PersonData();
    personData.FirstName = "John";
    personData.City = new MultilingualValue<string>();
    personData.City.Value[ Language.English] = "The Zurrieq";
    personData.City.Value[Language.French] = "Le Zurrieque";

    MultilingualValueData.CurrentLanguage = Language.English; 

    var personModel = Mapper.Map<PersonData, PersonModel>(personData);
}

public class MultilingualValueToBasicDataTypeConverter<T> : ITypeConverter<MultilingualValue<T>, T> 
{
    public T Convert(ResolutionContext context)
    {
        var currentLanguage = MultilingualValueData.CurrentLanguage; //THIS IS THE [ThreadStatic] VARIABLE
        if (currentLanguage == null) throw new InvalidOperationException("Please make sure to fill in CurrentLanguage");

        MultilingualValue<T> sourceMultilingualValue = (MultilingualValue < T > )context.SourceValue;

        T destinationValue = default(T);
        if (sourceMultilingualValue != null)
        {
            destinationValue = sourceMultilingualValue.Value[currentLanguage.Value];
        }

        return destinationValue;
    }
}        

public static class MultilingualValueData
{
    [ThreadStatic]
    public static Language? CurrentLanguage;
}

我认为配置在这个例子中是不必要的,因此我忽略了它们。如果您需要它们,我也可以发布它们。

虽然这样可以工作,但我觉得这种解决方法相当丑陋。有没有办法通过 ResolutionContext 传递数据?

1个回答

31

只需使用带有 Action<IMappingOperationOptions> 参数的 Map 重载方法。您可以将配置元素添加到 Items 属性中,然后传递给您的 ITypeConverter

public class CustomConverter : ITypeConverter<string, string>
{
    public string Convert(ResolutionContext context)
    {
        return "translated in " + context.Options.Items["language"];
    }
}

internal class Program
{
    private static void Main(string[] args)
    {
        AutoMapper.Mapper.CreateMap<string, string>().ConvertUsing<CustomConverter>();
        var result = AutoMapper.Mapper.Map<string, string>("value" , opt => opt.Items["language"] = "english");
        Console.Write(result); // prints "translated in english"
        Console.ReadLine();
    }
}

完美,正是我想要的! :) - Karl Cassar
1
我被迫使用一个不支持opt.Items的较旧版本的AutoMapper。有没有替代方案? - Jeroen Breuer
你如何向“Items”字典中添加2个元素? - M B
AutoMapper.Mapper.Map<string, string>("value", opt => opt.Items["language"] = "english") 的第二个参数是一个 lambda 表达式,你可以传递一个方法的地址来向你的字典添加键。 - samy

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