Подтвердить что ты не робот

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

Я десериализую класс под названием 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();
}
4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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

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

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

XmlSerializer..::. XmlSerializer (Тип, Строка)

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