В настоящее время я добавляю CodeContracts в свою существующую кодовую базу.
Одна вещь, которая оказывается трудной, — это использование сущностей, которые гидратированы NHibernate.
Предположим, что этот простой класс:
public class Post
{
private Blog _blog;
[Obsolete("Required by NHibernate")]
protected Post() { }
public Post(Blog blog)
{
Contract.Requires(blog != null);
_blog = blog;
}
public Blog Blog
{
get
{
Contract.Ensures(Contract.Result<Blog>() != null);
return _blog;
}
set
{
Contract.Requires(value != null);
_blog = value;
}
}
[ContractInvariantMethod]
private void Invariants()
{
Contract.Invariant(_blog != null);
}
}
Этот класс пытается защитить инвариант _blog != null
. Однако в настоящее время он терпит неудачу, потому что я легко могу создать экземпляр Post
, наследуя его и используя защищенный конструктор. В этом случае _blog
будет null
.
Я пытаюсь изменить свою кодовую базу таким образом, чтобы инварианты действительно были защищены.
Защищенный конструктор на первый взгляд нужен NHibernate для создания новых экземпляров, но есть способ обойти это требование.
Этот подход в основном использует FormatterServices.GetUninitializedObject
. Важным моментом является то, что этот метод не запускает никаких конструкторов.
Я мог бы использовать этот подход, и это позволило бы мне избавиться от защищенного конструктора. Статическая проверка CodeContracts теперь будет счастлива и больше не будет сообщать о нарушениях, но как только NHibernate попытается гидратировать такие сущности, она сгенерирует «инвариантные неудачные» исключения, потому что она пытается установить одно свойство за другим, и каждый установщик свойств выполняется. код, который проверяет инварианты.
Итак, чтобы все это работало, мне нужно убедиться, что сущности создаются через их общедоступный конструктор.
Но как мне это сделать?