Сериализация без 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();
}
Ответы
Ответ 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, как показано ниже Пример.