Коллеги,
В нашем проекте мы используем 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)));
Спасибо