Скажем, у меня есть этот простой класс в модуле называется ClassLibrary1
:Как я могу десериализовать объект, содержащий DataTable с значениями перечисления, используя DataContractSerializer?
[DataContract]
public class Class1
{
[DataMember]
private DataTable _data;
public void SetData(string key, object value)
{
_data = new DataTable("SomeName");
_data.Columns.Add("Key", typeof(String));
_data.Columns.Add("Value", value.GetType());
_data.Rows.Add(key, value);
}
}
и в отдельном модуле, называемом ClassLibrary2
, у меня есть следующий класс:
[DataContract]
public class Configuration
{
[DataMember]
private Class1 _obj;
public Configuration()
{
_obj = new Class1();
_obj.SetData("Key", MyEnum.Value2);
}
}
Кроме того, модуль ClassLibrary2
определяет перечисление называемый MyEnum
, который не помечен как общедоступный, т. е. он является внутренним для модуля (и используется в приведенном выше коде, как вы можете видеть).
Теперь, в моем основном модуле, я не хочу зависеть от ClassLibrary2
, но мне нужно загрузить его динамически во время выполнения. То есть, я использую, затем найдите тип, который мне нужно использовать (в моем простом примере я просто ищу тип с именем «Конфигурация») и создаю экземпляр, используя Activator.CreateInstance
. Затем я сериализую экземпляр так:
var ser = new DataContractSerializer(config.GetType());
var outstream = new FileStream("c:\\test.xml", FileMode.Create);
ser.WriteObject(outstream, config);
outstream.Close();
Пока все работает. Но когда я пытаюсь десериализации это так:
var instream = new FileStream("c:\\test.xml", FileMode.Open);
var conf = ser.ReadObject(instream);
я получаю ArgumentException
, с сообщением «Колонка требует действительного типа данных.» Я обнаружил, что это не произойдет, если я либо
- Определение MyEnum в главном модуле вместо
- Заменить DataTable с помощью простого
String key; Object value
- использовать что-то другое вместо перечисления MyEnum (например, строка)
Но ни один из этих вариантов не является очень желательным в моем реальном приложении. Первый вариант создаст сильную связь между модулями, которые не должны зависеть друг от друга. Второй вариант возможен, но немного много работы (я уже использую DataTable во многих местах по всему классу и только недавно обнаружил, что мне пришлось выполнять сериализацию), а третий вариант тоже беспорядочен.
Есть ли другие способы, которыми я могу заставить это работать? Я также попытался добавить MyEnum в список известных типов сериализатора, как через конструктор DataContractSerializer
, так и добавив [KnownType(typeof(MyEnum))]
перед объявлением класса Configuration
, но это не помогло.
Вы можете разместить свое объявление Enum? – aiapatag
Уверен: enum MyEnum {Value1, Value2, Value3} –
Вы пытались пометить свое перечисление как '[DataContract]' и каждый член как '[EnumMemberAttribute]'? – aiapatag