AutoMapper无法映射KeyValuePair<K,V>。

3
我正在构建一个通用的漂亮打印方法。我想要单独处理的特殊类型之一是 KeyValuePair<TK,TV>。为了将对象缩小到已知类型,我想将每个 KeyValuePair<TK,TV> 映射到 KeyValuePair<object, object>
下面的代码总是在 proxyKeyValue 属性中产生两个 null 值。
Mapper.CreateMap(o.GetType(), typeof(KeyValuePair<object, object>));
var proxy = Mapper.Map<KeyValuePair<object, object>>(o);

相比之下,这个非通用版本可以按照预期工作:

Mapper.CreateMap(o.GetType(), typeof(DictionaryEntry));
var proxy = Mapper.Map<DictionaryEntry>(o);

为什么?

o在这个阶段已经被测试为一个KeyValuePair<,>
我正在使用.NET 4.0上的AutoMapper 3.2.1.0。

1个回答

8

DictionaryEntryKeyValue都可以被设置。当你映射到DictionaryEntry时,AutoMapper会匹配KeyValue属性并将它们设置。

这在KeyValuePair<TKey, TValue>中是无法实现的,因为它是不可变的。因此,AutoMapper返回一个新的KeyValuePair<object, object>,其中KeyValue属性未设置。

通常情况下,你可以使用ConstructUsing来解决这个问题:

Mapper.CreateMap<KeyValuePair<string, string>, KeyValuePair<object, object>>()
    .ConstructUsing(kvp => new KeyValuePair<object, object>(kvp.Key, kvp.Value));

然而,由于您没有使用此版本的 CreateMap,这是不可能的。

不过,您可以创建一个简单的扩展方法来实现:

public static class KeyValuePairExtensions
{
    public static KeyValuePair<object, object> CastUp<TKey, TValue>(
        this KeyValuePair<TKey, TValue> kvp)
    {
        return new KeyValuePair<object, object>(kvp.Key, kvp.Value);
    }
}

然后使用它来代替AutoMapper:

var kvp = new KeyValuePair<string, string>("Hello", "World");
KeyValuePair<object, object> proxy = kvp.CastUp();

这样做可以避免您为每个使用的变体创建不同的映射定义。

我明白了,谢谢!关于答案的第二部分,那不是一个选项,因为此代码所在的方法会将KVP作为“object”引用获取,即类型参数未知。 - Mau
啊,我明白了,那真是不幸。 - Andrew Whitaker
@Mau:你可以先映射到DictionaryEntry,然后再映射到KeyValuePair<object, object>。这样的话,你就可以使用ConstructUsing方法了。 - Andrew Whitaker
当我有一个DictionaryEntry时,我只需静态构建一个KVP<object, object> :-) - Mau

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