我有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的重载方法。我无法弄清楚,如何让它调用正确的方法。谢谢你的帮助。
答案 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.');
我希望这会有所帮助。