2012-03-21 53 views
7

Objetivo final para serializar FirefoxDriver (mi pregunta aquí) = ¡hacer que WebDriver sea más rápido!.NET: serializar el objeto a un archivo de un ensamblado de un tercero (para hacer más rápido el Selenium WebDriver)

A continuación se muestra un enlace que describe cómo serializar un objeto. Pero requiere implementar desde ISerializable para el objeto que está serializando. Lo que me gustaría hacer es serializar un objeto que no definí: un objeto basado en una clase en un ensamblado de terceros (de una referencia de proyecto) que es que no implementa ISerializable. ¿Es eso posible? ¿Cómo puede hacerse esto?

http://www.switchonthecode.com/tutorials/csharp-tutorial-serialize-objects-to-a-file

Propiedad (IWebDriver = tipo de interfaz):

private IWebDriver driver; 

objeto de instancia (FireFoxDriver es un tipo de clase):

driver = new FirefoxDriver(firefoxProfile); 

===== ===========

3/21/2012 actualización después de la respuesta publicada

¿Por qué arrojaría un error? No le gusta esta línea:

serializedObject.DriverInstance = (FirefoxDriver)driver; 

...

error:

Cannot implicitly convert type 'OpenQA.Selenium.IWebDriver' to 'OpenQA.Selenium.Firefox.FirefoxDriver'. An explicit conversion exists (are you missing a cast?) 

Aquí está el código:

FirefoxDriverSerialized serializedObject = new FirefoxDriverSerialized(); 
    Serializer serializer = new Serializer(); 
    serializedObject = serializer.DeSerializeObject(@"C:\firefoxDriver.qa"); 
    driver = serializedObject.DriverInstance; 

    if (driver == null) 
    { 
     driver = new FirefoxDriver(firefoxProfile); 
     serializedObject.DriverInstance = (FirefoxDriverSerialized)driver; 
     serializer.SerializeObject(@"C:\firefoxDriver.qa", serializedObject); 
    } 

Aquí están los dos Seri alizer clases I construidos:

public class Serializer 
{ 
    public Serializer() 
    { 
    } 

    public void SerializeObject(string filename, FirefoxDriverSerialized objectToSerialize) 
    { 
     Stream stream = File.Open(filename, FileMode.Create); 
     BinaryFormatter bFormatter = new BinaryFormatter(); 
     bFormatter.Serialize(stream, objectToSerialize); 
     stream.Close(); 
    } 

    public FirefoxDriverSerialized DeSerializeObject(string filename) 
    { 
     FirefoxDriverSerialized objectToSerialize; 
     Stream stream = File.Open(filename, FileMode.Open); 
     BinaryFormatter bFormatter = new BinaryFormatter(); 
     objectToSerialize = (FirefoxDriverSerialized)bFormatter.Deserialize(stream); 
     stream.Close(); 
     return objectToSerialize; 
    } 
} 

[Serializable()] 
public class FirefoxDriverSerialized : FirefoxDriver, ISerializable 
{ 
    private FirefoxDriver driverInstance; 
    public FirefoxDriver DriverInstance 
    { 
     get { return this.driverInstance; } 
     set { this.driverInstance = value; } 
    } 

    public FirefoxDriverSerialized() 
    { 
    } 

    public FirefoxDriverSerialized(SerializationInfo info, StreamingContext ctxt) 
    { 
     this.driverInstance = (FirefoxDriver)info.GetValue("DriverInstance", typeof(FirefoxDriver)); 
    } 

    public void GetObjectData(SerializationInfo info, StreamingContext ctxt) 
    { 
     info.AddValue("DriverInstance", this.driverInstance); 
    } 
} 

=================

3/23/2012 update # 2 - serialización fija/de-serialización, pero teniendo otro problema

Esto corrigió el código de llamada. Porque estamos eliminando el archivo * .qa cuando llamamos a WebDriver.Quit() porque es cuando elegimos cerrar el navegador. Esto también matará a nuestro controlador en caché. Entonces, si comenzamos con una nueva ventana del navegador, golpearemos el bloque catch y crearemos una nueva instancia y la guardaremos en nuestro archivo * .qa (en forma serializada).

FirefoxDriverSerialized serializedObject = new FirefoxDriverSerialized(); 
    Serializer serializer = new Serializer(); 

    try 
    { 
     serializedObject = serializer.DeSerializeObject(@"C:\firefoxDriver.qa"); 
     driver = serializedObject.DriverInstance; 
    } 
    catch 
    { 
     driver = new FirefoxDriver(firefoxProfile); 
     serializedObject = new FirefoxDriverSerialized(); 
     serializedObject.DriverInstance = (FirefoxDriver)driver; 
     serializer.SerializeObject(@"C:\firefoxDriver.qa", serializedObject); 
    } 

Sin embargo, sigue recibiendo esta excepción:

Acu.QA.Main.Test_0055_GiftCertificate_UserCheckout: 
SetUp : System.Runtime.Serialization.SerializationException : Type 'OpenQA.Selenium.Firefox.FirefoxDriver' in Assembly 'WebDriver, Version=2.16.0.0, Culture=neutral, PublicKeyToken=1c2bd1631853048f' is not marked as serializable. 
TearDown : System.NullReferenceException : Object reference not set to an instance of an object. 

La tercera línea de este bloque de código es tirar la excepción:

public void SerializeObject(string filename, FirefoxDriverSerialized objectToSerialize) 
    { 
     Stream stream = File.Open(filename, FileMode.Create); 
     BinaryFormatter bFormatter = new BinaryFormatter(); 
     bFormatter.Serialize(stream, objectToSerialize); // <=== this line 
     stream.Close(); 
    } 

========== ==========

actualización # 3 - 3/24/2012 - simplificó la instancia de FirefoxDriver al no pasar nada al constructor. Lo haré más complejo más adelante al pasar FirefoxProfile al constructor. Todavía recibo la misma excepción que la actualización n. ° 2.

Código de llamada:

FirefoxDriverSerialized serializedObject = new FirefoxDriverSerialized(); 
Serializer serializer = new Serializer(); 
try 
{ 
    serializedObject = serializer.DeSerializeObject(@"C:\firefoxDriver.qa"); 
    driver = serializedObject.DriverInstance; 
} 
catch 
{ 
    //driver = new FirefoxDriver(firefoxProfile); 
    driver = new FirefoxDriver(); 
    serializedObject.DriverInstance = (FirefoxDriver)driver; 
    serializer.SerializeObject(@"C:\firefoxDriver.qa", serializedObject); 
} 

también tuvo que añadir ": base()" al constructor en mi clase de objeto serializado:

[Serializable()] 
public class FirefoxDriverSerialized : FirefoxDriver, ISerializable 
{ 
    private FirefoxDriver driverInstance; 
    public FirefoxDriver DriverInstance 
    { 
     get { return this.driverInstance; } 
     set { this.driverInstance = value; } 
    } 

    public FirefoxDriverSerialized() : base() 
    { 
    } 

    public FirefoxDriverSerialized(SerializationInfo info, StreamingContext ctxt) 
    { 
     this.driverInstance = (FirefoxDriver)info.GetValue("DriverInstance", typeof(FirefoxDriver)); 
    } 

    public void GetObjectData(SerializationInfo info, StreamingContext ctxt) 
    { 
     info.AddValue("DriverInstance", this.driverInstance); 
    } 
} 

====== =======

Actualización # 4 - acaba de documentar las firmas de código auxiliar para OpenQA.Selenium.Firefox.FirefoxDriver clase

using OpenQA.Selenium; 
using OpenQA.Selenium.Remote; 
using System; 

namespace OpenQA.Selenium.Firefox 
{ 
    public class FirefoxDriver : RemoteWebDriver, ITakesScreenshot 
    { 
     // CLASS DATA MEMBERS 

     //public static readonly bool AcceptUntrustedCertificates; 
     //public static readonly string BinaryCapabilityName; 
     //public static readonly bool DefaultEnableNativeEvents; 
     //public static readonly int DefaultPort; 
     //public static readonly string ProfileCapabilityName; 

     // CONSTRUCTORS 

     //public FirefoxDriver(); 
     //public FirefoxDriver(FirefoxProfile profile); 
     //public FirefoxDriver(ICapabilities capabilities); 
     //public FirefoxDriver(FirefoxBinary binary, FirefoxProfile profile); 
     //public FirefoxDriver(FirefoxBinary binary, FirefoxProfile profile, TimeSpan commandTimeout); 

     // PROPERTIES 

     protected FirefoxBinary Binary { get; } 
     protected FirefoxProfile Profile { get; } 

     // METHODS 

     //protected override RemoteWebElement CreateElement(string elementId); 
     //public Screenshot GetScreenshot(); 
     //protected void PrepareEnvironment(); 
     //protected override void StartClient(); 
     //protected override void StopClient(); 
    } 
} 
+0

Todavía estoy en el mismo problema, "bFormatter.Serialize (stream, objectToSerialize);" arroja una SerializationException. Encontraste una forma de resolverlo? – blueomega

+0

No recuerdo ese problema exacto, pero si su objeto hereda otro objeto, los objetos ancestros deben implementar ISerializable ... Me gustaría volver a ver esto pronto y terminar lo que comencé – MacGyver

Respuesta

5

Crear su propio objeto personalizado que se deriva de ISerializable y el objeto que desea serializar y serializar ese objeto personalizado. Este ejemplo específico no funcionará si el objeto de terceros es Sealed (hay otras formas que aún se pueden usar con ISerializable).

Actualizado por solicitud

Actualizado por pregunta de actualización

public class MyFirefoxDriver : FirefoxDriver, ISerializable 
{ 
    public MyFirefoxDriver(<Interface/Class> firefoxProfile) 
    :base(firefoxProfile) 
    { 
    } 

    void GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
    // Properties needing to be serialized 
    info.AddValue("SomeProperty", base.SomeProperty); 
    } 
} 

Actualización 2

Su nuevo código me está confundiendo. Creo que usted está buscando ..

serializedObject = serializer.DeSerializeObject(@"C:\firefoxDriver.qa"); 
driver = serializedObject; 

Esto se debe a FirefoxDriverSerialized es una FireFoxDriver.

Actualización 3

Es importante tener en cuenta que los constructores no son llamados cuando un objeto se deserialized. Esto significa que las cosas que normalmente están construidas/configuradas en el constructor no estarán en deserialización, lo que generalmente resulta en un NullReferenceException. La solución consiste en implementar ISerializable y explicity establecer los objetos necesarios para que la clase funcione (tanto para GetObjectData como para el constructor deserializador especial). Esto puede ser más difícil si la comprensión del objeto en cuestión no es simple ni si no tenemos la fuente para ello.

It is important to stress that you need to implement both GetObjectData as well as the special constructor when ISerializable is added to a class. The compiler will warn you if GetObjectData is missing, but since it is impossible to enforce the implementation of a constructor, no warnings will be given if the constructor is absent and an exception will be thrown when an attempt is made to deserialize a class without the constructor.

public class MyObject 
{ 
    public MyObject() 
    { 
    this.SomeOtherObject = new MyObject2(); 
    } 
    public string Name { get; set; } 
    public MyObject2 SomeOtherObject { get; set; } 
} 

public class MyObjectSerializable : MyObject, ISerializable 
{ 
    protected MyObjectSerializable(SerializationInfo si, StreamingContext context) 
    { 
    // base() is never called during deserialization 
    // so use the special ISerializable constructor to set the value of the object 
    // why not add it to the si.AddValue? 
    // because, most likely in this question, it is not a [Serializable] object either 
    // so we have to treat it differently as well 
    this.SomeOtherObject = new MyObject2(); 
    } 

    public override void GetObjectData(SerializationInfo si, StreamingContext context) 
    { 
    si.AddValue("Name", Name); 
    } 
} 
+0

¿me puede mostrar un ejemplo de lo que la firma de clase se vería en tu respuesta? – MacGyver

+0

Te mostraré un código de ejemplo ... en realidad es de un tipo de interfaz, no de un tipo de clase ... no estoy seguro de cuál debería usar. Ver mi edición para más detalles. – MacGyver

+1

Actualizado según su solicitud. –

1

No se requiere para heredar de ISerializable. Por defecto, el objeto debe heredar de ISerializable o decorarse con SerializableAttribute. Sin ninguno de ellos, su mejor opción es usar un SurrogateSelector. Esto le permitirá decirle al serializador que serialice otro objeto en su lugar en función de cómo defina su sustituto.

+0

Parece que sabe un poco más sobre estos objetos serializados. ¿Mi respuesta te parece correcta? Me encontré con este problema con Java hace años, y esto es lo que obtuve de él. Te voté de manera ascendente para que puedas compartir tus conocimientos sobre este tema. – MacGyver

Cuestiones relacionadas