为什么List <session>从以后的运行</session>获取其他会话

时间:2013-06-11 04:15:25

标签: c# fiddlercore

我正在使用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;
    }
}

列出oAllSessions_Test2和列表oAllSessions_Dev1是我的两个集合。当我调试捕获时,我通常会在oAllSessions_Test2集合中看到15行。然后在捕获oAllSessions_Dev1后,我看到计数已经上升了14或15,当我看到集合中包含的内容时,一些Dev1捕获现在就在那里。 oAllSessions_Dev1只有我期待的会话。我猜我必须有一个我不期待的指针,但我在这一点上难以理解如何清除它。我注意到的另一件事是会话计数器在应用程序循环遍历各种情况时继续递增。

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

那我在这里错过了什么?

2 个答案:

答案 0 :(得分: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

持有外部应用程序(fiddler)中的引用并为您管理它们。当您+ =并添加委托FiddlerApplication.AfterSessionComplete += tAction;时,fiddler应用程序将此添加到AfterSession事件触发时调用的方法列表中。

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

所以.....

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

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

答案 1 :(得分: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的代码转移到类的主体中。这将至少确定内联代表是否是问题的原因。