Принудительное оформление атрибутов классов/методов
Исходя из моего недавнего вопроса о больших, сложных объектах как результат веб-службы. Я думал о том, как обеспечить, чтобы все будущие дочерние классы были сериализуемыми в XML.
Теперь, очевидно, я мог бы реализовать интерфейс IXmlSerializable, а затем привязать к нему читателя/писателя, но я бы хотел этого избежать, так как тогда это означает, что мне нужно создавать экземпляр читателя/писателя всякий раз, когда я хочу это делать, и в 99,99% случаев Я собираюсь работать со строкой, поэтому я могу написать свою собственную.
Однако, чтобы сериализовать в XML, я просто украшаю класс и его членов Xml??? атрибуты (XmlRoot, XmlElement и т.д.), а затем передают их в XmlSerializer и StringWriter для получения строки. Что все хорошо. Я намереваюсь поместить метод для возврата строки в универсальный служебный метод, поэтому мне не нужно беспокоиться о типе и т.д.
Это касается меня: если я не украшаю класс необходимыми атрибутами, ошибка не выдается до времени выполнения.
Есть ли способ принудительного оформления атрибутов? Можно ли это сделать с помощью FxCop? (Я еще не использовал FxCop)
ОБНОВИТЬ:
Извините за задержку с этим, ребята, многое сделать!
Определенно, как идея использовать рефлексию, чтобы сделать это в тестовом примере, а не прибегать к FxCop (хотелось бы, чтобы все было вместе). Ответ Фредрика Калсета был фантастическим, спасибо за включение кода, так как это, вероятно, заняло бы у меня немного копаний выяснить, как это сделать самому!
+1 другим парням за подобные предложения :)
Ответы
Ответ 1
Я бы написал тест unit/integration, который проверяет, соответствует ли любой класс, соответствующий некоторым заданным критериям (например, подклассификация X). Если вы настроите свою сборку для запуска с помощью тестов, вы можете скомпилировать сборку, когда этот тест завершится с ошибкой.
UPDATE: Вы сказали: "Похоже, мне просто нужно свернуть рукава и убедиться, что модульные тесты поддерживаются вместе" - вам не обязательно. Просто напишите общий тестовый класс, который использует отражение, чтобы найти все классы, которые необходимо подтвердить. Что-то вроде этого:
[TestClass]
public class When_type_inherits_MyObject
{
private readonly List<Type> _types = new List<Type>();
public When_type_inherits_MyObject()
{
// lets find all types that inherit from MyObject, directly or indirectly
foreach(Type type in typeof(MyObject).Assembly.GetTypes())
{
if(type.IsClass && typeof(MyObject).IsAssignableFrom(type))
{
_types.Add(type);
}
}
}
[TestMethod]
public void Properties_have_XmlElement_attribute
{
foreach(Type type in _types)
{
foreach(PropertyInfo property in type.GetProperties())
{
object[] attribs = property.GetCustomAttributes(typeof(XmlElementAttribute), false);
Assert.IsTrue(attribs.Count > 0, "Missing XmlElementAttribute on property " + property.Name + " in type " + type.FullName);
}
}
}
}
Ответ 2
Вы можете написать модульные тесты для проверки такого рода вещей - в основном он использует отражение.
Учитывая тот факт, что это возможно, я думаю, было бы также возможно написать правило FxCop, но я никогда не делал такого.
Ответ 3
Вы можете написать правило FxCop или даже проверить атрибуты, вызвав GetType() в конструкторе базового класса и отразив возвращаемый тип.
Ответ 4
Хорошее правило FXCop (и тот, который я нахожу сейчас), должен проверить, что все объекты, которые добавляются в сеанс ASP.NET, имеют атрибут Serializable. Я пытаюсь перейти из состояния сеанса InProc в SQL Server. В первый раз, когда я попросил страницу, мой сайт взорвался, потому что несериализуемые объекты сохранялись в сеансе. Затем появилась задача поиска по всему исходному коду, ищущему каждый экземпляр, где объект задан в сеансе... FXCop будет хорошим решением. Что-то для работы над...
Ответ 5
Вы также можете использовать эту концепцию/пост-процессор для обеспечения отношений между атрибутами и использования аналогичного входа для обеспечения соблюдения отношений между классами и атрибутами во время компиляции:
http://www.st.informatik.tu-darmstadt.de/database/publications/data/cepa-mezini-gpce04.pdf?id=92