#c# #automapper
#c# #automapper
Вопрос:
Я использую AutoMapper
, и мне нужно игнорировать элементы, где an Attribute
не определен. Затем, если элемент не игнорируется, мне нужно сопоставить только те места, где определены значения. Мне удалось достичь этих двух по отдельности, но ForAllMembers
/ ForAllOtherMembers
, похоже, переопределяет первое правило.
Допустим, у меня есть этот класс:
public class Foo
{
[MyCustomAttribute]
public string Name { get; set; }
public string IgnoreMe { get; set; }
[MyCustomAttribute]
public int? DontIgnoreNumber { get; set; }
}
Я хочу игнорировать IgnoreMe
независимо. Затем, для Name
и DontIgnoreNumber
, я хочу сопоставить их, только если у них есть значение. Как я могу этого добиться?
Я пробовал это:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<Foo, Foo>()
.IgnoreAllNonAttributedEntities()
.ForAllOtherMembers(opts =>
{
opts.Condition((src, dest, srcMember) =>
{
// Check if source is a default value
return srcMember != null;
});
});
});
Я проверил, что ForAllOtherMembers
правило работает. И я, отдельно, проверил, что IgnoreAllNonAttributedEntities
работает. Когда я пытаюсь их объединить, ForAllOtherMembers
кажется, что они имеют приоритет.
IgnoreAllNonAttributedEntities
определяется как:
public static IMappingExpression<TSource, TDestination> IgnoreAllNonAttributedEntities<TSource, TDestination>
(this IMappingExpression<TSource, TDestination> expression)
{
var flags = BindingFlags.Public | BindingFlags.Instance;
//var sourceType = typeof(TSource);
var destinationType = typeof(TDestination);
foreach(var prop in destinationType.GetProperties(flags))
{
var attr = ReflectionHelpers.GetAttribute<MyCustomAttribute>(prop);
if (attr == null)
{
expression.ForMember(prop.Name, opt => opt.Ignore());
}
}
return expression;
}
Комментарии:
1. «Я хочу сопоставить их, только если у них есть значение»., если у этих свойств нет значения, он просто установит значение null или есть какой-либо другой сценарий, в котором это может быть проблемой?
2. Если это
null
илиdefault
, я не хочу сопоставлять, иначе сделайте сопоставление, если оноMyCustomAttribute
определено. Таким образом, условие для сопоставления == имеет атрибут И не является нулевым значением.3. Я в замешательстве… сопоставляются
Foo
ли они с самим собой? И еслиDontIgnoreNumber
равно Null, каким должно быть значение в результирующем объекте? Не забывайте, что AutoMapper инициализирует результирующий объект, поэтому это важно.4. @HoomanBahreini Да. У меня есть экземпляр
Foo
и другой экземплярFoo
. Оба уже инициализированы. Foo -> Foo. Если источникDontIgnoreNumbner
естьnull
, то результатDontIgnoreNumber
также должен бытьnull
.5. Тогда почему вы хотите это игнорировать? Разве вы не можете просто позволить Automapper скопировать источник в пункт назначения? Я не проверял это, но я считаю, что если source равно null, то назначение тоже будет null (не думаю, что вам нужно что-либо игнорировать).
Ответ №1:
Я только что запустил ваш код, и он работает так, как ожидалось. Однако, возможно, вас беспокоит значение по умолчанию для типов значений в c # (потому что вы проверяете только нули). Вот мое исправление для типов значений:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<Foo, Foo>()
.IgnoreAllNonAttributedEntities()
.ForAllOtherMembers(opts =>
{
opts.Condition((src, dest, srcMember) =>
{
var srcType = srcMember?.GetType();
if (srcType is null)
{
return false;
}
return (srcType.IsClass amp;amp; srcMember != null)
|| (srcType.IsValueType
amp;amp; !srcMember.Equals(Activator.CreateInstance(srcType)));
});
});
});
Я воссоздал ваш сценарий, используя последнюю версию automapper, доступную в NuGet (8.0.0.0).