C# Eventhandler:发送方强制转换与反射

C# Eventhandler:发送方强制转换与反射,c#,reflection,casting,C#,Reflection,Casting,我有一个可能很简单的问题,但我的知识并不能掩盖为什么我会有以下代码的不同行为: private void Test_ResultStateChangedEventHandler(object sender, EventArgs e) { Testcases.AbstractTestCase tc = (Testcases.AbstractTestCase)sender; System.Reflection.MethodInfo mInfo = sender.GetType().

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

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在运行时被更改

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

如果我更改了结果状态,那么我希望它是“未测试的”。测试启动后(在将值设置为“not_tested”的初始化之后紧随其后),此属性立即设置为“running”,从而引发事件

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

虽然反射按预期提供“未测试”,但直接强制转换将提供“正在运行”,即使调试器的单个步骤也表示“未测试”

值得一提的是,testcase正在另一个线程中运行,因此我假设在访问它的属性之前,该值已经被更改了

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

我更喜欢使用cast而不是反射,因为访问类成员需要一大堆代码

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

编辑1:更多的代码 _tcMngr只不过是一个类集合,允许动态运行不同的测试用例,并由伪类提供。Eventhandler和下面的代码正在UI线程中运行。AbstractTestCase正在新线程中运行

在UI线程中,Being启动了测试:

_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;
        }
    }
}
公共类伪:AbstractTestCase
{
公共重写字符串简短描述
{
得到
{
返回“Dummy for debug.”;
}
}
公共覆盖无效处置()
{
//这里没什么可做的
}
公共覆盖无效初始化()
{
base.TestResult=testcasesultstates.NotTested;
}
公共覆盖无效运行()
{
base.TestResult=testcasesultstates.Running;
对于(int i=1;i<11;i++)
{
系统线程线程睡眠(1000);
基本进度报告(i*10,“步骤”+i+“/10”);
}
base.TestResult=testcasesultstates.Fail;
base.TextResult=“测试已完成:\”“+base.TestResult.ToString()+”\”;
}
公共重写字符串ToString()
{
返回“Dummy”;
}
公共覆盖整数估计时间
{
得到
{
返回10;
}
}
}

因此您有两个不同的线程:一个线程正在使用
testcase执行某些操作(可能正在更改其状态),另一个线程调用事件?闻起来像是线程竞赛。或者不使用Type.GetProperty()的一些奇怪的结果。当你不给我们看房子的样子时,那只是瞎猜,没有意义。嗯。。我将尝试添加一些更相关的代码,但事实上没有这么多。请使用调试器。在TestResult属性设置器上设置一个断点,堆栈跟踪告诉您是什么代码更改了它的值。此值更改将引发事件,我希望反射比直接类型转换慢。我想知道为什么它不是完全相反的方式?然而,正如前面提到的,这种竞争条件可能会成为一个问题,因此我无论如何都要对我的代码做一些修改。