Ответ 1
Вы входите в мир Aspect Oriented Programming здесь. Вы могли бы сбить эту функциональность за 5 минут, используя PostSharp - но, похоже, вам не разрешено использовать внешние фреймворки. Таким образом, ваш выбор сводится к реализации вашей собственной очень простой инфраструктуры AOP или просто кусает пулю и добавляет проверки для каждого средства настройки свойств.
Лично я бы просто написал чек в настройщике свойств. Это может быть не так болезненно, как вы ожидаете. Вы можете написать фрагмент кода визуальной студийной студии, чтобы ускорить процесс. Вы также можете написать класс unit test, который, используя отражение, просматривал бы все свойства замороженного объекта и пытался установить значение - с помощью теста если не было исключено исключение.
EDIT В ответ на запрос VoodooChilds.. Вот краткий пример класса unit test, используя NUnit и отличную библиотеку FluentAssertions.
[TestFixture]
public class PropertiesThrowWhenFrozenTest
{
[TestCase(typeof(Foo))]
[TestCase(typeof(Bar))]
[TestCase(typeof(Baz))]
public void AllPropertiesThrowWhenFrozen(Type type)
{
var target = Activator.CreateInstance(type) as IFreezable;
target.Freeze();
foreach(var property in type.GetProperties())
{
this.AssertPropertyThrowsWhenChanged(target, property);
}
}
private void AssertPropertyThrowsWhenChanged(object target, PropertyInfo property)
{
// In the case of reference types, setting the property to null should be sufficient
// to test the behaviour...
object value = null;
// In the case of value types, just create a default instance...
if (property.PropertyType.IsValueType)
value = Activator.CreateInstance(property.PropertyType);
Action setter = () => property.GetSetMethod().Invoke(target, new object[] { value });
// ShouldThrow is a handy extension method of the FluentAssetions library...
setter.ShouldThrow<InvalidOperationException>();
}
}
Этот метод использует параметризованный unit test для прохождения в тестируемых типах, но вы также можете инкапсулировать весь этот код в общий базовый класс (где T: IFreezable) и создавать расширенные классы для каждого тестируемого типа, но некоторые тестовые бегуны не любят тесты в базовых классах. * ahem * Resharper! ahem
EDIT 2 и, просто для удовольствия, вот пример Gherkin script, который можно использовать для создания гораздо более гибких тестов для такого рода вещей:)
Feature: AllPropertiesThrowWhenFrozen
In order to make sure I haven't made any oversights in my code
As a software developer
I want to be able to assert that all properties of a class throw an exception when the object is frozen
Scenario: Setting the Bar property on the Foo type
Given I have an instance of the class MyNamespace.MyProject.Foo
And it is frozen
When I set the property Bar with a value of 10
Then a System.InvalidOperationException should be thrown