Есть ли другой способ создания контракта для класса модели LINQ-to-SQL? - PullRequest
1 голос
/ 24 июня 2009

В этом примере у меня есть два класса, которые являются частичными классами по отношению к классам модели LINQ-to-SQL.

public partial class Foo 
{
    public bool IsValid 
    {
        get { return (GetRuleViolations().Count() == 0); }
    }

    public IEnumerable<RuleViolation> GetRuleViolations() 
    {
        yield break;
    }

    partial void OnValidate(ChangeAction action) 
    {
        if (!IsValid)
            throw new ApplicationException("Rule violations prevent saving");
    }
}

public partial class Bar 
{
    public bool IsValid 
    {
        get { return (GetRuleViolations().Count() == 0); }
    }

    public IEnumerable<RuleViolation> GetRuleViolations() 
    {
        yield break;
    }

    partial void OnValidate(ChangeAction action) 
    {
        if (!IsValid)
            throw new ApplicationException("Rule violations prevent saving");
    }
}

Я бы хотел выделить эту функцию, чтобы удалить избыточную логику. Я попробовал это с интерфейсом IModel и затем методами расширения для контрактов, но это сломалось с частичным классом.

Я закончил с этим:

    public class ModelBase
    {
        public bool IsValid
        {
            get
            {
                return this.GetRuleViolations().Count() == 0;
            }
        }

        public void OnValidate(ChangeAction action)
        {
            if (!IsValid) throw new ApplicationException("Rule violations prevent saving");
        }

        public virtual IEnumerable<RuleViolation> GetRuleViolations() { return null; }
    }

public partial class Blog : ModelBase
{
    partial void OnValidate(ChangeAction action)
    {
        base.OnValidate(action);
    }

    public override IEnumerable<RuleViolation> GetRuleViolations()
    {
        // rules omitted
    }
}

Должен ли я сделать это по-другому? Спасибо.

1 Ответ

1 голос
/ 24 июня 2009

Единственное, что я хотел бы добавить к этому, это то, что вы можете определить интерфейс, а затем различные базовые классы, реализующие интерфейс для обеспечения некоторой проверки по умолчанию. Например, у вас может быть базовый класс, который выполняет XSS-проверку строковых свойств, проверяя, что они не содержат HTML. Использование интерфейса позволит вам наследовать любой из этих базовых классов (или даже просто интерфейс, если хотите) и при этом иметь возможность рассматривать их как интерфейс. Вы также можете рассмотреть вопрос о наличии подписи, позволяющей указать действие ChangeAction - у вас могут быть другие правила проверки для удаления, чем обновления или вставки.

public interface IValidatedEntity
{
    IEnumerable<RuleViolations> GetRuleViolations();
    IEnumerable<RuleViolations> GetRuleViolations( ChangeAction action );
}

public abstract class XSSValidatedEntity : IValidatedEntity
{
    public virtual IEnumerable<RuleViolations> GetRuleViolations()
    {
        return GetRuleViolations( ChangeAction.Insert );
    }

    public virtual IEnumerable<RuleViolations> GetRuleViolations( ChangeAction action )
    {
         if (action != ChangeAction.Delete)
         {
             return ValidateStringProperties();
         }
         return new List<RuleViolations>();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...