.NET:将对象序列化为来自第三方程序集的文件(以使Selenium WebDriver更快)

Mac*_*ver 7 .net performance serialization assemblies webdriver

序列化FirefoxDriver的最终目标(我的问题在这里)=使WebDriver更快!!

以下是描述如何序列化对象的链接.但它需要您从ISerializable实现您正在序列化的对象.我想要做的是序列化一个我没有定义的对象 - 一个基于第三方程序集(来自项目引用)中未实现ISerializable的类的对象.那可能吗?如何才能做到这一点?

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

属性(IWebDriver =接口类型):

private IWebDriver driver;
Run Code Online (Sandbox Code Playgroud)

对象实例(FireFoxDriver是类类型):

driver = new FirefoxDriver(firefoxProfile);
Run Code Online (Sandbox Code Playgroud)

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

回答发布后的3/21/2012更新

为什么会抛出错误?它不喜欢这一行:

serializedObject.DriverInstance = (FirefoxDriver)driver;
Run Code Online (Sandbox Code Playgroud)

...

错误:

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

这是代码:

    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);
    }
Run Code Online (Sandbox Code Playgroud)

这是我构建的两个Serializer类:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

2012年3月23日更新#2 - 修复了序列化/反序列化,但还有另一个问题

这修复了调用代码.因为我们在调用WebDriver.Quit()时删除了*.qa文件,因为那时我们选择关闭浏览器.这也将杀死我们的缓存驱动程序.因此,如果我们从一个新的浏览器窗口开始,我们将点击catch块并创建一个新实例并将其保存到我们的*.qa文件中(以序列化形式).

    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);
    }
Run Code Online (Sandbox Code Playgroud)

但是,仍然会遇到此异常:

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.
Run Code Online (Sandbox Code Playgroud)

此代码块中的第3行抛出异常:

   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();
   }
Run Code Online (Sandbox Code Playgroud)

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

更新#3 - 3/24/2012 - 通过不向构造函数传递任何内容来简化FirefoxDriver实例.稍后我会通过将FirefoxProfile传递给构造函数来使它更复杂.我仍然得到与更新#2相同的异常.

来电代码:

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);
}
Run Code Online (Sandbox Code Playgroud)

还必须在我的序列化对象类中为我的构造函数添加":base()":

[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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

更新#4 - 仅记录OpenQA.Selenium.Firefox.FirefoxDriver类的存根签名

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ips 5

创建您自己的自定义对象,ISerializable以及要序列化和序列化该自定义对象的对象.如果第三方对象是Sealed(还有其他方法仍然可以使用ISerializable),则此特定示例将不起作用.

每个请求更新

更新了每个问题更新

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

更新2

你的新代码令我困惑.我觉得你在找......

serializedObject = serializer.DeSerializeObject(@"C:\firefoxDriver.qa");
driver = serializedObject;
Run Code Online (Sandbox Code Playgroud)

这是因为FirefoxDriverSerializedFireFoxDriver.

更新3

重要的是要注意,在反序列化对象时不会调用构造函数.这意味着通常在构造函数中构造/设置的东西不会在反序列化时生成,这通常会导致a NullReferenceException.解决这个问题的方法是实现ISerializable和明确设置类所需的对象(GetObjectData和特殊的反序列化器构造函数).如果对所讨论的对象的理解不简单,或者我们没有它的来源,这可能是最困难的.

重要的是要强调,当将ISerializable添加到类时,您需要实现GetObjectData以及特殊构造函数.如果GetObjectData丢失,编译器会发出警告,但由于不可能强制执行构造函数,如果构造函数不存在,将不会发出警告,并且当尝试反序列化没有的类时会抛出异常构造函数.

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);
  }
}
Run Code Online (Sandbox Code Playgroud)