2008-12-16 15 views
12

Estoy deserializando una clase llamada Method usando .NET Serialization. Method contiene una lista de objetos que implementan IAction. Originalmente utilicé el atributo [XmlInclude] para especificar todas las clases que implementan IAction.Serializar sin XmlInclude

Pero ahora, me gustaría cambiar mi programa para cargar todos los dll en un directorio y quitar las clases que implementan IAction. A continuación, los usuarios pueden deserializar los archivos que contienen sus acciones implementando IAction.

Ya no controlo las clases que implementan IAction, por lo tanto no puedo usar [XmlInclude].

¿Hay alguna manera de establecer este atributo en el tiempo de ejecución? ¿O tiene un atributo similar establecido para la clase implementadora?

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

Respuesta

10

XmlSerializer tiene un constructor que acepta una matriz de tipos que serán aceptadas al deserializar:

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

Usted debe ser capaz de pasar su gama de assemblyTypes como segundo argumento.

6

Puede hacer una variedad de tipos en el Serializador Xml como lo ha demostrado David Norman. Una gran palabra de precaución. Cada vez que haces esto, se crea y compila un nuevo serializador xml. Si haces esto mucho, tendrás una enorme pérdida de memoria y rendimiento en tu mano.

Esto es una gran memoria y rendimiento de cerdo, asegúrese de hacerlo solo una vez. Puede resolver esto mediante el almacenamiento en caché el código XML Serializador: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx

de fragmentos de MSDN:

Asambleas generado dinámicamente Para aumentar el rendimiento, la infraestructura de serialización XML genera dinámicamente asambleas para serializar y deserializar los tipos especificados. La infraestructura encuentra y reutiliza esos conjuntos. Este comportamiento se produce sólo cuando se utilizan los siguientes constructores:

XmlSerializer .. :: XmlSerializer (Tipo)

XmlSerializer .. :: XmlSerializer (Type, String)

Si utiliza cualquiera de.. los otros constructores, se generan varias versiones del mismo ensamblaje y nunca se descargan, lo que da como resultado una fuga de memoria y un rendimiento deficiente. La solución más fácil es usar un de los dos constructores mencionados anteriormente. De lo contrario, debe almacenar en caché los ensamblajes en una tabla Hash, como se muestra en el siguiente ejemplo .