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

Я десериализую класс под названием Method, используя сериализацию .NET. 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();
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
12
0
5 720
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

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

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

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

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

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

Dynamically Generated Assemblies To increase performance, the XML serialization infrastructure dynamically generates assemblies to serialize and deserialize specified types. The infrastructure finds and reuses those assemblies. This behavior occurs only when using the following constructors:

XmlSerializer..::.XmlSerializer(Type)

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

If you use any of the other constructors, multiple versions of the same assembly are generated and never unloaded, which results in a memory leak and poor performance. The easiest solution is to use one of the previously mentioned two constructors. Otherwise, you must cache the assemblies in a Hashtable, as shown in the following example.

Другие вопросы по теме