将动态转换的实例传递给重载的方法c#

时间:2013-09-08 00:05:00

标签: c# dynamic casting overloading

我有c#应用程序。我有2个不同的类( Step1.State Step2.State )(它们实现了名为 IMDP.IState 的相同接口),它代表了应用程序状态执行我的应用程序的2个不同步骤。我有2个重载方法来更新应用程序状态。

我的方法中有以下代码:

Step1.State s1s = null;
Step2.State s2s = null;

然后我根据其类型转换当前状态。 currentState 是作为参数接收的已实现接口的实例。首先,我将其存储在动态类型中。

  //currentState is instance of IMDP.IState interface which is 
  //implemented by the two states

    dynamic curState=currentState;  

            if(curState is Step1.State)
            {
                s1s = (Step1.State)currentState;
                curState = s1s;

            }
            else if (curState is Step2.State)
            {
                s2as = (Step2.State)currentState;
                curState = s2s;

            }

然后我在同一个方法中调用我的重载方法。

  currentState = myAgent.UserStateUpdate(prevAction, curState, e.Result);

UserStateUpdate 方法有2个重载版本。第一个获得 Step1.State ,第二个获得 Step2.State 作为区分参数..如下所示;

IMDP.IState UserStateUpdate(IMDP.IAction act, Step1.State st, RecogResult rr)
IMDP.IState UserStateUpdate(Step2.Abuse.Action act, Step2.State st, RecogResult rr)

应用程序调用 Step1.State 的正确方法,但是当应用程序移动到Step2时,使用 Step2.State 进行状态表示。它抛出以下异常。请注意,当我在调用重载方法之前检查存储在 curState (键入的动态)中的内容时,我看到的是正确的状态,其类型为 Step2.State

'BI4A.Agent.Agent.UserStateUpdate(BI4A.IMDP.IAction,BI4A.Step1.State,System.Speech.Recognition.RecognitionResult)的最佳重载方法匹配'有一些无效的参数

这基本上表明系统试图调用接受Step1.State而不是Step2.State的重载方法。我无法弄清楚,如何让它调用正确的方法。谢谢你的帮助。

1 个答案:

答案 0 :(得分:1)

艾伦,

问题不在于State参数。我已使用下面的代码验证了这一点:

class Program
{
    interface IState
    {
    }

    class State1 : IState
    {
    }

    class State2 : IState
    {
    }

    private static void UpdateState(State1 s1)
    {
        Console.WriteLine("State1 Updated.");
    }

    private static void UpdateState(State2 s1)
    {
        Console.WriteLine("State2 Updated.");
    }

    static void Main(string[] args)
    {
        var random = new Random(123456);
        var i = 10;

        while (i-- > 0)
        {
            var n = random.Next();

            dynamic curStep = (n % 2) == 0 ? (dynamic)new State1() : new State2();

            UpdateState(curStep);
        }

        Console.ReadKey();
    }
}

然而,问题似乎是因为第一个参数中的类型不匹配。即IMDP.IAction和Step2.Abuse.Action。当我用action参数修改上面的代码时,我得到了同样的错误。修改后的代码如下:

class Program
{
    interface IState
    {
    }

    class State1 : IState
    {
    }

    class State2 : IState
    {
    }

    interface IAction
    {
    }

    class SomeAction : IAction
    {
    }

    private static void UpdateState(IAction act, State1 s1)
    {
        Console.WriteLine("State1 IAction Updated.");
    }

    private static void UpdateState(SomeAction act, State2 s1)
    {
        Console.WriteLine("State2 SomeAction Updated.");
    }

    static void Main(string[] args)
    {
        var random = new Random(123456);
        var i = 10;
        IAction act = new SomeAction();

        while (i-- > 0)
        {
            var n = random.Next();

            dynamic curStep = (n % 2) == 0 ? (dynamic)new State1() : new State2();

            UpdateState(act, curStep);
        }

        Console.ReadKey();
    }
}

在网上挖掘后,我遇到了以下链接,提到这是一个知道错误。 https://connect.microsoft.com/VisualStudio/feedback/details/597276/dynamic-runtime-fails-to-find-iset-t-contains-during-runtime

另外,请参阅stackoverflow条目 Passing a dynamic parameter throws RuntimeBinderException when calling Method from Inherited interface

建议的解决方案:我建议您将第二种方法的动作参数类型从Step2.Abuse.Action更改为IMDP.IAction。我知道这不是一个优雅的解决方案,但它的工作原理。要确保只允许Step2.Abuse.Action类型的对象,可以像这样检查对象类型和throw和exception:

if (!(act is Step2.Abuse.Action))
    throw new Exception('Invalid Action Type.');

我希望这会有所帮助。