2016-12-21 2 views
2

Мне нравится использовать nameof() в моем приложении Core .NET при установке ошибок mvc с помощью ModelState.AddModelError(). Это уменьшает скрытые ошибки, поскольку здесь я передаю имя атрибута. По сравнению со строкой, это имеет то преимущество, что ошибка компилятора возникает, когда атрибут был переименован.Используйте имяof(), чтобы получить атрибут для ModelState.AddModelError()

Пример

class MyModel{ 
    public string Name{get;set;} 
} 
public class MyController:Controller{ 
    public IActionResult Test(MyModel model) { 
     // Will hiddenly fail when "Name" is renamed to something else 
     ModelState.AddModelError("Name", "The Name field is required!"); 

     // Better: Using the auto renaming feature of VS, this will be updated if "Name" was renamed 
     ModelState.AddModelError(nameof(model.Name), "The Name field is required!"); 
    } 
} 

Это работает, пока у меня есть еще один объект:

class MyModel{ 
    public string Name{get;set;} 
    public MyOtherModel OtherModel{get;set;} 
} 
class MyOtherModel{ 
    public string OtherName{get;set;} 
} 

Теперь я хочу, чтобы получить имя OtherModel. Проблема: для ASP.NET требуется шаблон BaseClass.ChildClass, поэтому OtherModel.OtherName в этом примере. Используя ту же логику, как и выше:

public class MyController:Controller{ 
    public IActionResult Test(MyModel model) { 
     ModelState.AddModelError(nameof(model.MyOtherModel.OtherName), "The Name field is required!"); 
    } 
} 

будет просто дать мне имя атрибута ребенка, так OtherName в этом примере. Но мне нужно OtherModel.OtherName. Есть ли чистый способ получить это без создания самой строки?

Это было бы возможно делать что-то вроде этого:

string actionName = nameof(model.MyOtherModel) + "." + nameof(model.MyOtherModel.OtherName); 

Но не очень чистый и интуитивный способ имхо.

+2

Я думаю, что построение самой струны - ваш единственный вариант. 'nameof' получает только имя вашей цепочки. –

+0

BaseClass.ChildClass немного вводит в заблуждение, поскольку эти термины относятся к наследованию. – Neme

+0

Напишите вспомогательный метод (или, возможно, метод расширения), который завершает неприглядные биты. Теперь ваш оставшийся код чист. –

ответ

2

Как и другие, вам, вероятно, придется написать свой собственный метод для этого. Это то, что я пришел с использованием Linq.Expressions:

string NameOfMember(Expression<Func<Model, object>> accessor) 
{ 
    string str = accessor.Body.ToString(); 
    return str.Substring(str.IndexOf('.') + 1); 
} 

Вы бы затем использовать его как это: NameOfMember(model => model.MyOtherModel.OtherName)

Я не знаком с ASP.NET, но вы можете изменить модель для любого типа вас хочет, включая объект.

В качестве примечания стороны не следует повторять «Поле имени обязательно!» в вашем коде. Возможно, вы можете включить это и в свой вспомогательный метод.

Смежные вопросы