Сериализация без XmlInclude - PullRequest
       16

Сериализация без XmlInclude

12 голосов
/ 16 декабря 2008

Я десериализирую класс с именем Method с использованием .NET Serialization. Method содержит список объектов, реализующих IAction. Первоначально я использовал атрибут [XmlInclude], чтобы указать все классы, которые реализуют IAction.

Но теперь я хотел бы изменить свою программу, чтобы загрузить все библиотеки DLL в каталог и удалить классы, которые реализуют IAction. Затем пользователи могут десериализовать файлы, содержащие их действия, реализующие IAction.

Я больше не управляю классами, которые реализуют IAction, поэтому я не могу использовать [XmlInclude].

Есть ли способ установить этот атрибут во время выполнения? Или есть аналогичный атрибут, установленный для реализующего класса?

public class Method
{
    public List<Actions.IAction> Actions = new List<Actions.IAction>();
}

public interface IAction
{
    void DoExecute();
}

public static Type[] LoadActionPlugins(string pluginDirectoryPath)
{
    List<Type> pluginTypes = new List<Type>();

    string[] filesInDirectory = Directory.GetFiles(pluginDirectoryPath, "*.dll", SearchOption.TopDirectoryOnly);
    foreach (string pluginPath in filesInDirectory)
    {
        System.Reflection.Assembly actionPlugin = System.Reflection.Assembly.LoadFrom(pluginPath);
        Type[] assemblyTypes = actionPlugin.GetTypes();
        foreach (Type type in assemblyTypes)
        {
            Type foundInterface = type.GetInterface("IAction");
            if (foundInterface != null)
            {
                pluginTypes.Add(type);
            }
        }
    }

    return pluginTypes.Count == 0 ? null : pluginTypes.ToArray();
}

Ответы [ 2 ]

10 голосов
/ 16 декабря 2008

XmlSerializer имеет конструктор, который принимает массив типов, которые будут приняты при десериализации:

public XmlSerializer(
   Type type,
   Type[] extraTypes
);

Вы должны быть в состоянии передать свой массив assemblyTypes в качестве второго аргумента.

6 голосов
/ 16 декабря 2008

Вы можете добавить массив типов в сериализатор Xml, как показал Дэвид Норман. Одно огромное слово предостережения. Каждый раз, когда вы делаете это, создается и компилируется новый сериализатор xml. Если вы будете делать это много, у вас будет огромная утечка памяти и снижение производительности.

Это огромная проблема с памятью и производительностью, убедитесь, что вы делаете это только один раз. Вы можете решить эту проблему путем кэширования вашего сериализатора xml: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx

Фрагмент из MSDN:

Динамически генерируемые сборки Для повышения производительности XML инфраструктура сериализации динамически генерирует сборки сериализовать и десериализовать указанные типы. Инфраструктура находит и повторно использует эти сборки. Такое поведение происходит только при использовании следующие конструкторы:

XmlSerializer .. ::. XmlSerializer (Тип)

XmlSerializer .. ::. XmlSerializer (Type, String)

Если вы используете какой-либо из других конструкторов, несколько версий одна и та же сборка генерируется и никогда не выгружается, что приводит к утечка памяти и низкая производительность. Самое простое решение - использовать один из ранее упомянутых двух конструкторов. В противном случае вы должны кэшировать сборки в Hashtable, как показано в следующем Пример.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...