为什么List从以后的运行中获取额外的会话

本文关键字:获取 会话 运行 为什么 Session 从以后 List | 更新日期: 2023-09-27 18:18:00

我使用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来启动浏览器会话,但我不认为这与这个特定问题特别相关。

我在这里错过了什么?

为什么List<Session>从以后的运行中获取额外的会话

这样做:

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

FiddlerApplication。

......

//在返回语句之前的结尾:

 FiddlerApplication.AfterSessionComplete -= tAction;

事情是这样的。

this: FiddlerApplication.Startup(8877, FiddlerCoreStartupFlags.Default);

(特别是)FiddlerApplication

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

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

所以…

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

要阻止它,你必须添加:FiddlerApplication.AfterSessionComplete -= tAction;,它告诉系统"嘿,不要再向这个方法推送更新了。它已经完成了接收通知。"

在。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的代码移到类的主体中。这至少可以确定内联委托是否是问题的原因。