Использование имени дает только имя поля, но не родительские поля.
Вы можете объединить nameof
s следующим образом:
nameof(MyModelType.EmbeddedObject) + "." + nameof(MyModel.EmbeddedObject.Id)
, что дает EmbeddedObject.Id
как nameof
, всегда будет приводить к последнему сегменту цепочки выражений.Просто создайте строку, копая на один уровень глубже с каждым выражением.
В качестве альтернативы вы можете написать вспомогательное выражение для выражения LINQ:
public static string GetFullPropertyPath<TModel,TProp>(Expression<Func<TModel,TProp>> expr)
{
return String.Join(".", GetMemberList(expr.Body as MemberExpression));
}
public static List<string> GetMemberList(MemberExpression expression)
{
var result = new List<string>();
if (expression.Expression is MemberExpression memberExpression)
{
result.AddRange(GetMemberList(memberExpression));
}
result.Add(expression.Member.Name);
return result;
}
GetMemberList
возвращает выбранную цепочку элементов безпараметр.Таким образом, если вы предоставите выражение, такое как m => m.EmbeddedObject.Id
, оно вернет [ "EmbeddedObject", "Id" ]
, которое при объединении с .
s приведет к EmbeddedObject.Id
.
GetFullPropertyPath
просто возвращает список членов ввыражение объединяется с символом .
. Здесь - это слегка измененная онлайн-демонстрация, которая не допускает синтаксис is MemberExpression memberExpression
.
В качестве примечания я бы также предложил попробовать библиотеку FluentValidation , который, хотя и дает слегка отличающийся по структуре ответ на валидацию, по моему мнению, гораздо более универсален, чем встроенный атрибут валидации.