同事 在我们的项目中,我们使用AutoMapper来映射模型。
我们有一个模特:
public class Location
{
public string Address { get; set; }
}
public class Person
{
public string Name { get; set;}
public Collection<Location> Locations { get; set; }
}
我们也有一个视图模型:
public class PersonView
{
public string Name { get; set; }
public string Location { get; set;}
}
要将模型映射到视图模型,我们可以定义如下内容:
Mapper.CreateMap<Person, PersonView>(d=>d.Name, opt=>opt.FromMap(s=>s.Name);
Mapper.CreateMap<Person, PersonView>(d=>d.Address, opt=>opt.FromMap(s=>s.Locations.First().Address);
但是:如果Locations不包含元素或者为null,那么我们将得到一个例外。
从另一方面,我们可以定义一个函数来获取值:
Mapper.CreateMap<Person, PersonView>(d=>d.Address, opt=>opt.FromMap(s=>
{
var item = s.Locations.FirstOrDefault();
if(item == null)
{
return string.Empty;
}
return item.Address;
});
这个表达难以阅读。我尝试创建一个IValueResolver来简化映射。
public class CollectionItemResolver<TSource, TSourceItem, TResult>
where TSource : class
where TSourceItem : class
{
private readonly Func<TSource, IEnumerable<TSourceItem>> _sourceSelector;
private readonly Func<TSourceItem, TResult> _selector;
private readonly TResult _defaultValue;
public CollectionItemResolver(Func<TSource, IEnumerable<TSourceItem>> source, Func<TSourceItem, TResult> selector)
: this(source, selector, default(TResult))
{
}
public CollectionItemResolver(Func<TSource, IEnumerable<TSourceItem>> source, Func<TSourceItem, TResult> selector, TResult defaultValue)
{
_sourceSelector = source;
_selector = selector;
_defaultValue = defaultValue;
}
public TResult Resolve(TSource source)
{
var items = _sourceSelector(source);
if (items == null)
{
return _defaultValue;
}
var item = items.FirstOrDefault();
if (item == null)
{
return _defaultValue;
}
var value = _selector(item);
return value;
}
}
然后使用这样的东西:
Mapper.CreateMap<Person, PersonView>(d=>d.Address, opt=>opt.ResolveUsing(
new CollectionItemResolver<Person, Location, string>(p=>p.Locations, i=>i.Address)));
可以简化通用解析器吗? 例如,不要定义嵌套项的类型?
new CollectionItemResolver<Person, string>(p=>p.Locations, i=>i.Address)));
谢谢,
答案 0 :(得分:1)
这个怎么样:
Mapper.CreateMap<Person, PersonView>(d=>d.Address, opt=>opt.FromMap(s=>s.Locations.Select(loc=>loc.Address).FirstOrDefault());
买方,Automapper
知道如何将Null
转换为string.Empty
PS,希望你的集合Locations
始终不为空。
但如果没有,那么我建议使用这个extension:
public static IEnumerable<TSource> NullToEmpty<TSource>(
this IEnumerable<TSource> source)
{
if (source == null)
return Enumerable.Empty<TSource>();
return source;
}
然后结果将是这样的: 选择=&GT; opt.FromMap(S =&GT; s.Locations.NullToEmpty()选择(LOC =&GT; loc.Address).FirstOrDefault());