Получение типа подкласса в базовом классе? - PullRequest
3 голосов
/ 07 февраля 2010

Я пытаюсь использовать методы проверки предприятия Microsoft для проверки своих организаций. В моем базовом классе у меня есть следующий метод:

public class BaseEntity
{
  public bool IsValid()
  {
     return Validate().IsValid;
  }

  public ValidationResults Validate()
  {
     return Validation.Validate<this.GetType()>(this);
}

Проблема в том, что даже когда подкласс BaseEntity вызывает IsValid, this.GetType () всегда возвращает BaseEntity, а не тип подкласса. Я не хочу переписывать этот код для каждой сущности, так как это выглядит не совсем так. Есть ли другой способ сделать это?

У меня была идея создать защищенную переменную защищенного типа _validationType, и в каждой сущности установить для него значение .GetType этой сущности, но, похоже, должен быть лучший способ сделать это.

Обновление
По-видимому this.GetType (), кажется, работает, как я и надеялся. Не уверен, почему этого не было раньше.

Я также изменил метод Validate (), чтобы использовать следующий код:

 return ValidationFactory.CreateValidator(this.GetType()).Validate(this);

Ответы [ 5 ]

2 голосов
/ 09 февраля 2010

Когда вы используете маппер O / RM, такой как LINQ to SQL, NHibernate или LINQ to Entities (ADO.NET Entity Framework), я бы использовал другой подход проверки. Я бы держал сущности полностью чистыми от проверки (поэтому там нет BaseEntity.Validate (). Вы можете переместить эту логику проверки в ObjectContext (EF) / DataContext (L2S) / Session (NH) и запустить проверку во время отправки базы данных). Посмотрите на пример ниже для LINQ to SQL:

public partial class NorthwindDataContext
{
    public override void SubmitChanges(ConflictMode failureMode)
    {
        var invalidResults = (
            from entity in this.GetChangedEntities()
            let type = entity.GetType()
            let validator = ValidationFactory.CreateValidator(type)
            let results = validator.Validate(entity)
            where !results.IsValid
            from result in results
            select result).ToArray();            

        if (invalidResults.Length > 0)
        {
            // You should define this exception type
            throw new ValidationException(invalidResults);
        }

        base.SubmitChanges(failureMode);
    }

    private IEnumerable<object> GetChangedEntities()
    {
        ChangeSet changes = this.GetChangeSet();
        return changes.Inserts.Concat(changes.Updates);
    }
}

В случае, если ваши объекты недействительны, будет выдано исключение ValidationException. Вы можете перехватить это конкретное исключение и выполнить итерацию свойства InvalidResults, которое вы для него определили.

Если вам нужна дополнительная информация, советую прочитать эту статью. Также описано, как это сделать с помощью Entity Framework.

Удачи.

2 голосов
/ 07 февраля 2010

Это very un-OO like для базового класса, чтобы знать что-либо о подклассах. Это работает так, как должно работать.

Если вы хотите что-то узнать о подклассах, вам нужно переопределить этот метод.

1 голос
/ 06 февраля 2011

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

Ну ... способ притворяться, по крайней мере(не нарушая правила OO, Габриэль).Это очень элегантно и прекрасно работает:

public ValidationResults Validate<TEntity>(this TEntity e) where TEntity : BaseEntity
{
   return Validation.Validate<TEntity>(e);
}

Большое преимущество метода расширения среди других ...:)

0 голосов
/ 07 февраля 2010

Перемещение логики типов из BaseEntity является более чистым.

public class BaseEntity
{
    public bool IsValid()
    {
        return Validate().IsValid;
    }

    public ValidationResults Validate()
    {
        return Validation.Validate(this);
    }
}
public class Validation
{
    public static ValidatorResults Validator<T>( T entity )
        where T : BaseEntity
    {
        return ValidationFactory.CreateValidator(entity.GetType()).Validate(entity);
    }
}
0 голосов
/ 07 февраля 2010

Вы можете сделать IsValid() и Validate() виртуальным методом для предоставления некоторых пользовательских определений в подклассах.

...