2015-12-11 2 views
0

В настоящее время я разрабатываю приложение, связанное с базой данных, но не использует EntityFramework для создания объектов базы данных. Вместо этого я создал пользовательские классы, которые обрабатывают сущности. Поля внутри этих объектов также используют пользовательские классы. Вот краткий пример:Использование FluentValidation с пользовательскими свойствами в приложении winform C#

public class BookEntity : Entity 
{ 
    public Field BookId {get; set;} 
    public Field Name {get; set;} 
    public Field Page {get; set;} 

    public BookEntity() 
    { 
     BookId = new Field("Books_BookId"); 
     Name = new Field("Books_Name"); 
     Page = new Field("Books_Page"); 
    } 
} 

public class Field 
{ 
    public String Viewfield{get; set;} 
    public Object Value{get; set;} 
} 

Как вы можете видеть, мой Field класс содержит два свойства. Первый содержит имя поля (с именем таблицы), а другое - значение.

Моя проблема заключается в том, что с использованием FluentValidation я хотел бы иметь возможность установить имя возвращаемого свойства в мое свойство Viewfield. В настоящее время я могу это сделать, используя расширения WithState, однако мне нужно будет указать его при каждом правильном правиле проверки.

private class BookValidator : AbstractValidator<Book> 
{ 
    /// <summary> 
    /// Constructor that contains all the validation rules 
    /// </summary> 
    public BookValidator() 
    { 
     RuleFor(p => (Double?)p.Page.Value) 
      .NotNull().WithState(p => p.Page.Viewfield) 
      .LessThanOrEqualTo(p => 1000).WithState(p => p.Page.Viewfield) 
      .GreaterThanOrEqualTo(p =>100).WithState(p => p.Page.Viewfield) 
    } 
} 

я стараюсь делать это с PropertyNameResolver, но так как я не могу получить доступ к экземпляру книги в то время как в распознаватель, я не могу получить доступ к Viewfield собственности.

Что бы я хотел, это то, что могло бы избежать повторения WithState.

Также обратите внимание, что я не могу использовать пользовательские атрибуты в своем поле, чтобы установить Viewfield.

Я надеюсь, что я хорошо объяснил себя,

Спасибо.

+0

Это просто слишком сложный способ не использовать ORM ... – DavidG

+0

Почему вы просто не использовали 'public int BookId {get; установить;} '? и то же самое для других свойств. –

+0

Я хотел бы иметь возможность сделать это, даже перенести рамки в EntityFramework, но я в настоящее время не могу. Как сказал @DavidG, это слишком сложный способ не использовать ORM, но я должен работать с этим на данный момент. – Yannick

ответ

0

Я не знаю FluentValidation, но я думаю, что ваша реализация действительно слишком странная, чтобы ее можно было поддерживать, возможно, у FluentValidation есть какой-то подключаемый механизм, чтобы получить значение свойства, которое вы можете подключить, но я сомневаюсь ... во всяком случае нечетное для нечетного (btw, что действительно странно: D), вы можете обернуть все FluentAPI в свое собственное расширение, например NotNullEx, LessThanOrEqualToEx и т. д.

Эти расширения имеют только один параметр, более уважающий корреспондент FluentAPI, а затем в эти расширения, которые вы называете валидатором FluentValidation, и возвращаете его результат, чтобы вы могли свободно связывать синтаксис

например

RuleFor(p => (Double?)p.Page.Value) 
     .NotNull().WithState(p => p.Page.Viewfield) 

может стать

RuleFor(p => (Double?)p.Page.Value) 
     .NotNullEx(p => p.Page.Viewfield) 

это не поможет вам много Тхо, потому что вам нужно в любом случае, чтобы указать, что селектор Linq (или прямой значение параметра, если вы позволяете расширение принимает строку, чтобы выбрать свойство имя)

Другой способ - создать свои собственные валидаторы, которые наследуются от оригинала, и подключить их к FluentValidator, так или иначе вы должны передать это значение свойства, поэтому я не думаю, что это было бы идеальным решением в любом случае

Обновление: Чтение расширения WithState здесь https://github.com/JeremySkinner/FluentValidation/blob/c101786a923406acff6029b00f664a91a097a9af/src/FluentValidation/DefaultValidatorOptions.cs Мне кажется, что вы можете просто позвонить в WithState после RuleFor (...), А не для каждой проверки линии

так вместо

RuleFor(p => (Double?)p.Page.Value) 
    .NotNull().WithState(p => p.Page.Viewfield) 
    .LessThanOrEqualTo(p => 1000).WithState(p => p.Page.Viewfield) 
    .GreaterThanOrEqualTo(p =>100).WithState(p => p.Page.Viewfield) 

вы можете попробовать с

RuleFor(p => (Double?)p.Page.Value) 
    .NotNull() 
    .WithState(p => p.Page.Viewfield) 
    .LessThanOrEqualTo(p => 1000) 
    .GreaterThanOrEqualTo(p =>100) 

ли это работает?

+0

Да, я считаю, что моя текущая структура просто не так хороша, чтобы поддерживать фреймворк FluentValidation. Я попытался сделать расширение, но мне пришлось бы переопределить весь процесс проверки FluentValidation, чтобы сохранить свое пользовательское значение до тех пор, пока не вернется ValidationResult. Хотя это может сработать, это намного сложнее, чем дублирование строки '.WithState' на каждом шаге правила проверки. (Спасибо за помощь, хотя!: D) – Yannick

+0

Вы уверены, что вам нужно указать WithState для всех видов проверки в одном поле? Мне кажется, чтение расширения WithState здесь https://github.com/JeremySkinner/FluentValidation/blob/c101786a923406acff6029b00f664a91a097a9af/src/FluentValidation/DefaultValidatorOptions.cs, которое вы могли бы просто назвать после RuleFor (...) –

+0

Я не удалось вызвать его после RuleFor, потому что WithState является расширением 'IRuleBuilderOptions', в то время как RuleFor возвращает' IRuleBuilderInitial' . Я попытался создать собственное расширение WithState с помощью 'IRuleBuilderInitial', и это действительно сработало. Однако при настройке конфигурации это дало мне ошибку, потому что конфигурация еще не была создана (ORNS). – Yannick