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





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.