Eventhandler:Sender-cast vs. reflection

时间:2016-02-15 09:00:16

标签: c# reflection casting

我有一个可能很简单的问题,但我的知识并未掩盖为什么我使用以下代码获得不同的行为:

private void Test_ResultStateChangedEventHandler(object sender, EventArgs e)
{
    Testcases.AbstractTestCase tc = (Testcases.AbstractTestCase)sender;

    System.Reflection.MethodInfo mInfo = sender.GetType().BaseType.GetMethod("get_TestResult");

    object retval = mInfo.Invoke(sender, new object[] { });

    if (retval != tc.TestResult) 
        throw new ArgumentException(); // Just to get a hold
}

我得到了抽象基类 AbstractTestCase ,其中属性 TestResult 在运行时被更改。

初始值为“Undefined”,其更改不应引发ResultStateChangedEventHandler。到目前为止还可以。

如果我改变结果状态,那么我希望它是“not_tested”。在测试开始之后(紧接在将值设置为“not_tested”的初始化之后),此属性设置为“running”,从而导致事件触发。

现在我得到了两个不同的结果,这取决于我是通过反射访问这个抽象类,还是我将我的发送者转换为我的 AbstractTestCase 类类型。

虽然反射按预期提供“not_tested”,但即使使用调试器的单步也说“not_tested”,直接转换将提供“运行”。

值得一提的是,测试用例在不同的线程中运行,因此我认为在访问它的属性之前该值已经被更改。

这让我感到困惑的原因是因为我认为反射比我通过将发送者强制转换为我的 tc 变量而创建的实例引用更慢。

我更喜欢使用强制转换而不是反射,因为只需要一大堆代码就可以访问类成员。

那么我的错误在哪里?如果反射较慢,为什么我的演员比慢反射慢?谢谢:))

编辑1:更多代码

_tcMngr 只不过是一个允许动态运行不同测试用例的类集合,并且由虚拟类提供。 Eventhandler和下面的代码在UI Thread中运行。 AbstractTestCase 正在新线程中运行。

在UI线程中开始测试:

_tcMngr.Initialize(identifier);

var t = Task.Factory.StartNew(() =>
{
    _tcMngr.RunSingle(identifier);
});

这是在运行时设置的属性:

public abstract class AbstractTestCase : TestReport, IStdTestCase
{
    public delegate void StatusChangedEventHandler(object sender, StatusChangedEventArgs e);

    public event StatusChangedEventHandler StatusChanged;

    protected virtual void OnStatusChanged(StatusChangedEventArgs e)
    {
        if (StatusChanged != null)
            StatusChanged(this, e);
    }

    protected virtual void ReportProgress(int percentage, string step, int maxPercentage = 100)
    {
        OnStatusChanged(new StatusChangedEventArgs()
        {
            Percentage = percentage,
            Step = step,
            MaxPercentage = maxPercentage               
        });
    }

    public class StatusChangedEventArgs : EventArgs
    {
        public int Percentage { get; set; } = 0;
        public int MaxPercentage { get; set; } = 100;
        public string Step { get; set; } = "";
    }

    public abstract void Run();
    public abstract void Dispose();
    public abstract string ShortDescription {
        get;
    }

    public virtual int EstimatedRuntime { get; } = 100;

    public abstract override string ToString();
    public abstract void Initialize();

    public int Identifier { get; set; }
}

public abstract class TestReport {
    public enum TestCaseResultStates
    {
        Running = 2,
        Success = 1,
        Fail = 0,
        Undefined = -1,
        NotTested = int.MaxValue
    }


    TestCaseResultStates _testresult = TestCaseResultStates.Undefined;

    public TestCaseResultStates TestResult
    {
        get
        {
            return _testresult;
        }

        set
        {
            _testresult = value;

            OnResultStateChanged(null);
        }
    }
}

这是一个用于调试的虚拟测试用例:

public class Dummy : AbstractTestCase
{
    public override string ShortDescription
    {
        get
        {
            return "Dummy for debugging.";
        }
    }

    public override void Dispose()
    {
        // nothing to do here
    }

    public override void Initialize()
    {
        base.TestResult = TestCaseResultStates.NotTested;
    }

    public override void Run()
    {
        base.TestResult = TestCaseResultStates.Running;

        for (int i = 1; i < 11; i++)
        {
            System.Threading.Thread.Sleep(1000);

            base.ReportProgress(i * 10, "Step " + i + " / 10");
        }

        base.TestResult = TestCaseResultStates.Fail;
        base.TextResult = "Test was finished: \"" + base.TestResult.ToString() + "\"";
    }

    public override string ToString()
    {
        return "Dummy";
    }

    public override int EstimatedRuntime
    {
        get
        {
            return 10;
        }
    }
}

0 个答案:

没有答案