XmlSerializer генерирует InvalidOperationException при использовании ограничения общего типа, где - PullRequest
7 голосов
/ 02 марта 2010

Когда я пытаюсь запустить следующий код (две отдельные сборки)

ClassLibrary.cs

public interface ITest
{
}

Program.cs

using System;

public class TestClass
{
    public void Test<T>(T x) where T : ITest { }
}

static class Program
{ 
    static void Main(string[] args)         
    {
        new System.Xml.Serialization.XmlSerializer(typeof(TestClass));
    }
}

Скомпилировано в 64-разрядной версии Windows 7 с использованием следующих команд:

c: \ Windows \ Microsoft.NET \ Framework \ v2.0.50727 \ csc / target: library ClassLibrary.cs

c: \ Windows \ Microsoft.NET \ Framework \ v2.0.50727 \ csc /reference:ClassLibrary.dll Program.cs

Я получаю это исключение:

System.InvalidOperationException: невозможно создать временный класс (Результат = 1). ошибка CS0012: тип ITest определяется в сборке, которая не ссылается Вы должны добавить ссылка на сборку ClassLibrary, Версия = 0.0.0.0, Культура = нейтральная, PublicKeyToken = null hinzu.

в System.Xml.Serialization.Compiler.Compile (Собрание родитель, строка нс, XmlSerializerCompilerParameters xmlParameters, Доказательства)
в System.Xml.Serialization.TempAssembly.GenerateAssembly (XmlMapping [] xmlMappings, Type [] types, String defaultNamespace, Доказательства, XmlSerializerCompilerParameters параметры, сборка сборки, Hashtable сборки) в System.Xml.Serialization.TempAssembly..ctor (XmlMapping [] xmlMappings, Type [] types, String defaultNamespace, расположение строки, Доказательства доказательства) на System.Xml.Serialization.XmlSerializer.GenerateTempAssembly (XmlMapping xmlMapping, Type type, String defaultNamespace) в System.Xml.Serialization.XmlSerializer..ctor (Тип тип String defaultNamespace) в Program.Main (String [] args)

Удаление , где T: ITest из TestClass или не использование универсальных шаблонов вообще (например, использование public void Test (ITest x) ) предотвратит исключение от того, чтобы быть брошенным, но мне нужна эта конструкция в моем реальном приложении.

Кто-нибудь понимает, почему XmlSerializer не может обработать ограничение where?

Ответы [ 3 ]

6 голосов
/ 02 марта 2010

Я думаю, вам не повезло . Вот ответ от Microsoft об этой проблеме:

Спасибо за отправку этой проблемы. К сожалению, мы решили, что это не будет рассматриваться, потому что риск исправления перевешивает его выгоду. От время следующей возможности сделать это изменение происходит, надежда что новая сериализация технологии в будущей версии Windows Communication Foundation рассмотрим ваш сценарий. Если это проблема вызывает существенный негативный влияние на бизнес, пожалуйста, свяжитесь с Служба поддержки продуктов Microsoft. я жалею, что мы не смогли обеспечить лучшее разрешение. Будьте уверены, что мы серьезно рассмотрели этот вопрос - Не исправить решение никогда не легко сделать.

В основном это говорит о том, что вы должны использовать DataContractSerializer вместо XmlSerializer или изменить структуру объекта.

3 голосов
/ 04 марта 2010

На самом деле, вы можете быть ОЧЕНЬ близко, и даже не знать об этом.

Попробуйте определить пустой вспомогательный класс внутри вашей сборки ClassLibrary и поместите [Serializable, XmlInclude(SerializationReferenceHelper)] чуть выше public class TestClass.

Проблема в том, что анализатор Xml не знает о втором классе, потому что он находится в другой сборке и на него ссылается только ограничение where в вашем коде. Да, Microsoft могла бы написать несколько мелочей, чтобы посмотреть все известные сборки ... не знаю, почему они этого не делают. Но сейчас это может сработать.

ClassLibrary

public class SerializationReferenceHelper { }
public interface ITest { }

Программа

[Serializable, XmlInclude(typeof(SerializationReferenceHelper))]
public class TestClass
{
    public void Test<T>(T x) where T : ITest { }
}

static class Program
{ 
    static void Main(string[] args)         
    {
        new System.Xml.Serialization.XmlSerializer(typeof(TestClass));
    }
}
0 голосов
/ 02 марта 2010

Тип ITest определяется в сборка, на которую нет ссылок. You необходимо добавить ссылку на сборку ClassLibrary

Ты это сделал?

...