首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C# TargetInvocationException和FormatException

C# TargetInvocationException和FormatException
EN

Stack Overflow用户
提问于 2015-07-06 03:10:39
回答 1查看 231关注 0票数 0

好吧,我这里发生了一个非常奇怪的情况。首先,我需要介绍一些背景知识。我正在为一个在XNA引擎上制作的游戏创建AI代理。按照设置的方式,人们应该使用代理的框架来生成一个.dll,然后游戏在运行时使用它来加载代理。

我可以访问游戏的代码(这样我就可以看到发生了什么),在这一点上,我正在使用别人的代理作为我自己的起点。最近,游戏(以及相应的框架)发生了一些变化,主要是在类和接口的名称上,这意味着我必须提高代理的速度。因此,在我进行了所有必要的更新,以便能够使用新版本的框架编译代理之后,我遇到了一个问题。这是游戏加载.dll的代码

代码语言:javascript
运行
复制
 // dynamically load assembly from file GeometryFriendsAgents.dll
 Assembly agentsDLL = Assembly.LoadFile(path);

 // get type of classes BallAgent and SquareAgent from just loaded Assembly
 Type circleType = AgentsDLL.GetType("GeometryFriendsAgents.CircleAgent");
 Type rectangleType = AgentsDLL.GetType("GeometryFriendsAgents.RectangleAgent");
 try { 
     // create instances of classes BallAgent and SquareAgent
     npcCircle = (ICircleAgent)Activator.CreateInstance(circleType);
     npcRectangle = (IRectangleAgent)Activator.CreateInstance(rectangleType);
 }catch(TargetInvocationException e){
     throw e.InnerException;
 }

我可以确认路径是正确的。当我尝试运行游戏时,try/catch内的行将抛出一个TargetInvocationException (它将自动加载代理)。我添加了try/catch来查看内部异常,它是一个FormatException,VisualStudio给出了输入字符串格式不正确的附加信息。

我不知道代理代码的哪一部分会与此相关,但我还没有讲到奇怪的部分。在我使用的实现中,代理使用LearningCenter类。这个类本质上是读写agent的学习文件。在课程开始时,它存储学习文件的路径:

代码语言:javascript
运行
复制
protected const string path = @"..\..\..\..\Agents\";

这就是事情变得奇怪的地方。这是学习文件的正确路径。当我之前犯了一个错误时,我将这个路径(之前在代码中重复了很多次)设置为

代码语言:javascript
运行
复制
protected const string path = @"..\..\..\..\Agents";

当我用不正确的路径构建.dll时,我可以成功地加载代理,它将运行游戏。因此,问题是路径不正确,当LearningCenter尝试写入学习文件时,它将明显失败,并显示DirectoryNotFoundException。有问题的方法是:

代码语言:javascript
运行
复制
public void EndGame(float knownStatesRatio) {
    if (_toSave) {
        FileStream fileStream = new FileStream(path + _learningFolder + "\\Ratios.csv", FileMode.Append);
        StreamWriter sw = new StreamWriter(fileStream);
        sw.WriteLine(knownStatesRatio);
        sw.Close();
        fileStream.Close();
        fileStream = new FileStream(path + _learningFolder + "\\IntraPlatformLearning.csv", FileMode.Create);
        DumpLearning(fileStream, _intraplatformPlayedStates);
        fileStream.Close();
        if (interPlatform) {
            fileStream = new FileStream(path + _learningFolder + "\\InterPlatformLearning.csv", FileMode.Create);
            DumpLearning(fileStream, _interplatformPlayedStates);
            fileStream.Close();
            }
        }
    }

当创建新的文件流时,会立即发生异常。我尝试将缺少的\转移到_learningFolder变量,但当我这样做时,又回到了第一个问题。只要路径不正确,我就可以运行游戏..。

我还应该提到,在此之前,我最初在同一位置遇到了另一个TargetInvocationException。当时,通过将代理类的可见性更改为public,修复了该问题。

我意识到路径的问题可能隐藏了实际的问题,但我只是不知道下一步该往哪里看。

编辑:这是第一个问题的堆栈跟踪

代码语言:javascript
运行
复制
GeometryFriends.exe!GeometryFriends.AI.AgentsManager.LoadAgents() Line 396
GeometryFriends.exe!GeometryFriends.Levels.SinglePlayerLevel.LoadLevelContent() Line 78
GeometryFriends.exe!GeometryFriends.Levels.Level.LoadContent() Line 262
GeometryFriends.exe!GeometryFriends.ScreenSystem.ScreenManager.LoadContent() Line 253
Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.DrawableGameComponent.Initialize() 
GeometryFriends.exe!GeometryFriends.ScreenSystem.ScreenManager.Initialize() Line 221 
Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.Game.Initialize() 
GeometryFriends.exe!GeometryFriends.Engine.Initialize() Line 203
Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.Game.RunGame(bool useBlockingRun)
Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.Game.Run()
GeometryFriends.exe!GeometryFriends.Program.Main(string[] args) Line 16

首先失败的代理是CircleAgent,下面是构造函数:

代码语言:javascript
运行
复制
public CircleAgent() {
    //Change flag if agent is not to be used
    SetImplementedAgent(true);

    lastMoveTime = DateTime.Now;
    lastRefreshTime = DateTime.Now;
    currentAction = 0;
    rnd = new Random(DateTime.Now.Millisecond);

    model = new CircleWorldModel(this);

    learningCenter = new CircleLearningCenter(model);
    learningCenter.InitializeLearning();

    startTime = DateTime.Now;
}

编辑2:好的,我设法找到了FormatException的源码。错误出现在CircleLearningCenter的这个方法中(第一个if中的语句):

代码语言:javascript
运行
复制
public override void addStateMovementValue(string[] lineSplit, string stateId, ref Dictionary<string, Dictionary<int, double>> lessons) {
    if (!lineSplit[1].Equals("0")) {
        lessons[stateId].Add(Moves.ROLL_LEFT, double.Parse(lineSplit[1]));
    }
    if (!lineSplit[2].Equals("0")) {
        lessons[stateId].Add(Moves.ROLL_RIGHT, double.Parse(lineSplit[2]));
    }
    if (!lineSplit[3].Equals("0")) {
        lessons[stateId].Add(Moves.JUMP, double.Parse(lineSplit[3]));
    }
}

它由LearningCenter中的此方法调用:

代码语言:javascript
运行
复制
private void createLearningFromFile(FileStream fileStream, ref Dictionary<string, Dictionary<int, double>> lessons) {
    lessons = new Dictionary<string, Dictionary<int, double>>();
    StreamReader sr = new StreamReader(fileStream);
    string line;
    while ((line = sr.ReadLine()) != null) {
        string[] lineSplit = line.Split(',');
        string stateId = lineSplit[0];
        lessons.Add(stateId, new Dictionary<int, double>());
        addStateMovementValue(lineSplit, stateId, ref lessons);
    }
}

该方法(在circle的构造函数中调用该方法):

代码语言:javascript
运行
复制
public void InitializeLearning() {
    if (File.Exists(Path.Combine(Path.Combine(path, _learningFolder), "IntraPlatformLearning.csv"))) {
        FileStream fileStream = new FileStream(Path.Combine(Path.Combine(path, _learningFolder),"IntraPlatformLearning.csv"), FileMode.Open);
        createLearningFromFile(fileStream, ref _intraplatformLessonsLearnt);
        fileStream.Close();
    } else {
        createEmptyLearning(ref _intraplatformLessonsLearnt);
    }
    if (File.Exists(Path.Combine(Path.Combine(path, _learningFolder), "InterPlatformLearning.csv"))) {
        FileStream fileStream = new FileStream(Path.Combine(Path.Combine(path, _learningFolder), "InterPlatformLearning.csv"), FileMode.Open);
        createLearningFromFile(fileStream, ref _interplatformLessonsLearnt);
        fileStream.Close();
     } else {
         createEmptyLearning(ref _interplatformLessonsLearnt);
     }
}

在不明显的情况下,CircleLearningCenter是LearningCenter的子类。另外,为文字墙感到抱歉,但我已经无计可施了。

EN

回答 1

Stack Overflow用户

发布于 2015-07-06 05:05:28

使用System.IO.Path.Combine()对路径零件进行cat。例如:

代替:

代码语言:javascript
运行
复制
FileStream(path + _learningFolder + "\\Ratios.csv")

使用:

代码语言:javascript
运行
复制
FileStream(Path.Combine(Path.Combine(path , _learningFolder) , "Ratios.csv"))

但不要忘记从每个部分中删除\。并对其他FileStream路径执行相同的操作。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31234026

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档