Это точно правильно, потому что компилятор должен знать, какой тип он предназначен для распределения. Поэтому классы шаблонов, функции, перечисления и т. Д. Должны быть реализованы также в файле заголовка, если он должен быть опубликован или частично из библиотеки (статический или динамический), поскольку файлы заголовков НЕ скомпилированы в отличие от файлов c / cpp, которые находятся. Если компилятор не знает, что тип не может его скомпилировать. В .Net это возможно, потому что все объекты происходят из класса Object. Это не .Net.
Вы не можете сделать это полностью с помощью общих ограничений, но вы можете сделать пару вещей, которые помогут:
1) Поместите new () ограничение для универсального типа (чтобы включить возможность десериализации и гарантировать, что XmlSerializer не жалуется на отсутствие ctor по умолчанию):
where T : new()
2) В первой строке вашего метода, обрабатывающего сериализацию (или конструктора, или где-то еще, что вам не нужно повторять снова и снова), вы можете выполнить эту проверку:
if( !typeof(T).IsSerializable && !(typeof(ISerializable).IsAssignableFrom(typeof(T)) ) )
throw new InvalidOperationException("A serializable Type is required");
Конечно, все еще существует возможность исключений времени выполнения при попытке сериализации типа, но это покроет наиболее очевидные проблемы.
Я написал в блоге длинную статью на эту тему, которая может быть вам полезна. В основном это касается двоичной сериализации, но эти концепции применимы практически к любому формату сериализации.
Короче говоря,
Единственный способ узнать, является ли объект сериализуемым, - это попытаться сериализовать его.
Фактически, вы спрашивали, как определить, является ли тип «сериализуемым», но на самом деле вопрос будет в отношении объектов. Некоторые экземпляры типа могут быть не сериализуемыми, даже если тип помечен как [Сериализуемый]. Например, что, если экземпляр содержит циклические ссылки?
Вместо
XmlSerializer xmlSerializer = new XmlSerializer (typeof (T));
попробуйте
XmlSerializer xmlSerializer = новый XmlSerializer (message.GetType ());