2008-12-16 5 views
12

Je désérialise une classe appelée Method en utilisant la sérialisation .NET. Method contient une liste d'objets implémentant IAction. J'ai initialement utilisé l'attribut [XmlInclude] pour spécifier toutes les classes qui implémentent IAction.Sérialisation sans XmlInclude

Mais maintenant, je voudrais changer mon programme pour charger toutes les DLL dans un répertoire et supprimer les classes qui implémentent IAction. Les utilisateurs peuvent ensuite désérialiser les fichiers contenant leurs actions en implémentant IAction.

Je ne contrôle plus les classes qui implémentent IAction, donc je ne peux pas utiliser [XmlInclude].

Existe-t-il un moyen de définir cet attribut lors de l'exécution? Ou avez un ensemble d'attributs similaire pour la classe d'implémentation?

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(); 
} 

Répondre

10

XmlSerializer a un constructeur qui accepte un tableau de types qui seront acceptés lorsque désérialisation:

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

Vous devriez être en mesure de passer votre tableau de assemblyTypes comme second argument.

6

Vous pouvez un tableau de types dans le sérialiseur Xml comme David Norman a montré. Un énorme mot d'avertissement. Chaque fois que vous faites cela, un nouveau sérialiseur xml est construit et compilé. Si vous faites cela beaucoup, vous aurez une énorme fuite de mémoire et de performance porc sur votre main.

Il s'agit d'une énorme mémoire et de performance, assurez-vous de ne le faire qu'une seule fois. Vous pouvez résoudre ce problème en mettant en cache votre xml sérialiseur: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx

Snippet de MSDN:

Assemblées Dynamiquement Generated pour améliorer la performance, l'infrastructure de sérialisation XML génère dynamiquement des ensembles à sérialisation et la désérialisation types spécifiés. L'infrastructure trouve et réutilise ces assemblages. Ce problème se produit uniquement lorsque vous utilisez les constructeurs suivants:

XmlSerializer .. :: XmlSerializer (Type)

XmlSerializer .. :: XmlSerializer (Type, String)

Si vous utilisez l'un.. les autres constructeurs, plusieurs versions du même assemblage sont générées et ne sont jamais déchargées, ce qui entraîne une fuite de mémoire et de mauvaises performances. La solution la plus simple consiste à utiliser un des deux constructeurs mentionnés précédemment. Sinon, vous devez mettre en cache les assemblages dans une table de hachage, comme indiqué dans l'exemple suivant.