0

我正在使用 fiddlercore 来捕获会话信息,以对特定响应中的数据进行比较。我注意到我不明白的一件事是,我正在将会话信息从第二个环境获取到第一个环境的 List 集合中。

public class ManageCompares
{
    public static string _test2BaseURL = "https://test2/";
    public static string _dev1BaseURL = "http://dev1/";


    private void RunCompares(string email, string handler, Reporting report)
    {
        ManageProcess.ShutDownProcess("iexplore");

        RunExports exportTest2 = new RunExports();
        RunExports exportDev1 = new RunExports();

        string password = "d";

        List<Session> oAllSessions_Test2 = exportTest2.RunExportGeneration
          (email, password, _test2BaseURL, handler);

        ManageProcess.ShutDownProcess("iexplore");

        List<Session> oAllSessions_Dev1 = exportDev1.RunExportGeneration
            (email, password, _dev1BaseURL, handler);

        exportTest2.ExtractResponse(oAllSessions_Test2, handler, report);

        //report.SetEnvironment2Body(ManageExports.ExtractResponse
        //  (oAllSessions_Dev1, handler, report, report.Environment2));

        if (report.Test2ResponseCode != 500 && report.Dev1ResponseCode != 500)
        {
            bool matches = CompareExports.CompareExportResults
              (report.Environment1Body, report.Environment2Body);

            if (matches)
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("Exports matched");
                Console.ResetColor();
            }
            else
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Export does not match");
                Console.ResetColor();

                report.GenerateReportFiles();
            }
        }
        else
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine
              ("A exception was returned.  Please review the log file.");
            Console.ResetColor();


        }
    }


}

public class RunExports
{
    public List<Session> RunExportGeneration
     (string email, string password, string baseUrl, 
          string handlersUrlwithParams)
    {
        IWebDriver driver = new InternetExplorerDriver();

        FiddlerApplication.Startup(8877, FiddlerCoreStartupFlags.Default);

        List<Session> oAllSessions = new List<Session>();

        LoginPage login = new LoginPage(driver);

        FiddlerApplication.AfterSessionComplete += delegate(Session oS)
        {
            Monitor.Enter(oAllSessions);
            oAllSessions.Add(oS);
            Monitor.Exit(oAllSessions);
        };

        try
        {
            driver.Navigate().GoToUrl(baseUrl);
            login.LoginToView(email, password);
            driver.Navigate().GoToUrl(baseUrl + handlersUrlwithParams);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
        finally
        {
            FiddlerApplication.Shutdown();                
            driver.Quit();
        }

        return oAllSessions;
    }
}

List oAllSessions_Test2 和 List oAllSessions_Dev1 是我的两个集合。当我调试捕获时,我通常会在 oAllSessions_Test2 集合中看到 15 行。然后在捕获 oAllSessions_Dev1 之后,我看到计数上升了 14 或 15,当我查看集合中包含的内容时,一些 Dev1 捕获现在在那里。oAllSessions_Dev1 只是我期待的会话。我猜一定有一个我没想到的地方有一个指针,但我现在很难过如何清除它。我注意到的另一件事是,当应用程序在各种情况下循环时,会话计数器会继续增加。

我也在使用 Selenium WebDriver 和 IE 来启动浏览器会话,但我认为这与这个特定问题并不特别相关。

那么我在这里错过了什么?

4

2 回答 2

1

做这个 :

SessionStateHandler tAction = oS =>
        {
            Monitor.Enter(oAllSessions);
            oAllSessions.Add(oS);
            Monitor.Exit(oAllSessions);
        };

FiddlerApplication.AfterSessionComplete += tAction;

......

//在你的return语句之前的最后:

 FiddlerApplication.AfterSessionComplete -= tAction;

这就是正在发生的事情。

这个: FiddlerApplication.Startup(8877, FiddlerCoreStartupFlags.Default);

(特别是这个)FiddlerApplication

在外部应用程序(提琴手)中保留引用并为您管理它们。当您 += 并添加一个委托FiddlerApplication.AfterSessionComplete += tAction;时,提琴手应用程序将其添加到它在 AfterSession 事件触发时调用的方法列表中。

因为它是单例的(您只在代码中处理一个 Fiddler 应用程序实例),所以每次执行 += 时都会将其添加到同一个列表中。每次调用方法时都不会重新创建 FiddlerApplication 中的此列表。它与您第一次调用的相同,因此即使您的委托超出了它的范围声明空间(就像本地对象通常在方法中所做的那样),FiddlerApplication EventList 维护对它的引用并每次触发该委托(并且每隔一个)。

所以.....

在您的方法中,您List<Session> oAllSessions = new List<Session>();可以在委托中创建和访问它。这个局部变量现在被传递回调用方法,List<Session> oAllSessions_Test2 = exportTest2.RunExportGeneration....委托 FiddlerApplication 调用是完全相同的列表。因此,每次您调用该方法并且 AfterSessionComplete 触发时,它都会更新列表,即使它已返回给调用函数。

要停止它,您必须添加:FiddlerApplication.AfterSessionComplete -= tAction;它告诉系统“嘿,不要再向此方法推送更新。它已完成接收通知。”

于 2013-06-11T20:24:00.543 回答
0

在 .NET 语言中,类对象几乎在所有情况下都是通过引用传递的。如果将对象引用分配给变量,则该变量仍将引用原始对象。对原始文件的更改将通过所有引用可见。这类似于过去在 C/C++ 中将指针或对结构的引用存储在内存中时发生的事情。实现细节不同,但结果是一样的。

下面是一个示例,说明当您存储稍后可能会更改的列表实例时会发生什么:

class ListTest
{
    List<string> l = new List<string>();
    public List<string> GetList() { return l; }
    public void Add(string v) { l.Add(v); }
}

class Program
{
    static void Main(string[] args)
    {
        ListTest t = new ListTest();
        t.Add("a"); t.Add("b"); t.Add("c"); t.Add("d");
        List<string> x1 = t.GetList();
        List<string> x2 = t.GetList().ToList();
        t.Add("e"); t.Add("f"); t.Add("g"); t.Add("h");
        List<string> y1 = t.GetList();
        List<string> y2 = t.GetList().ToList();

        Console.WriteLine("{0}, {1}", x1.Count, y1.Count);
        Console.WriteLine("{0}", string.Join(", ", x1));
        Console.WriteLine("{0}", string.Join(", ", y1));

        Console.WriteLine();

        Console.WriteLine("{0}, {1}", x2.Count, y2.Count);
        Console.WriteLine("{0}", string.Join(", ", x2));
        Console.WriteLine("{0}", string.Join(", ", y2));
    }
}

当您运行它时,您会得到一组相同的结果,因为x1y1是对同一对象的引用。第二组结果不同,因为调用ToList创建了一个新List<string>实例来保存结果。

这可能是您的 Fiddler 代码返回的列表所发生的情况。

-- 代码审查后更新

它看起来是您分配给AfterSessionComplete事件的委托导致代码被oAllSessions视为绑定到事件处理程序委托的静态对象。当您开始使用生成闭包的代码等时,会发生各种类似的副作用。

我建议更改代码以使用类方法而不是内联方法 - 将您的oAllSessions变量和您分配给的代码AfterSessionComplete移到类的主体中。这至少可以确定内联委托是否是问题的原因。

于 2013-06-11T04:47:31.400 回答