簡體   English   中英

C#TargetInvocationException和FormatException

[英]C# TargetInvocationException and FormatException

好的,我這里發生的情況很奇怪。 首先,我需要提供一些背景知識。 我正在為XNA引擎制作的游戲創建AI代理。 設置方式的方式是,人們應該使用代理的框架來生成一個.dll,游戲在運行時便會使用該.dll來加載代理。

我可以訪問游戲的代碼(因此我可以看到發生了什么),此時,我正在使用別人的代理作為自己的起點。 最近,對游戲(以及相應的框架)進行了一些更改,主要是在類和接口的名稱上進行了更改,這意味着我必須加快代理的速度。 因此,在完成所有必要的更新以便能夠使用新版本的框架編譯代理后,我想到了一個問題。 這是游戲加載.dll的代碼

 // 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類。 此類實際上是讀寫代理的學習文件。 在課程開始時,它存儲學習文件的路徑:

protected const string path = @"..\..\..\..\Agents\";

因此,這里的事情變得很奇怪。 這是學習文件的正確路徑。 早些時候我犯了一個錯誤,我有這個路徑(之前在整個代碼中多次重復)

protected const string path = @"..\..\..\..\Agents";

當我使用錯誤的路徑構建.dll時,我可以成功加載代理,它將運行游戲。 然后的問題是路徑不正確,並且當LearningCenter嘗試寫入學習文件時,它顯然會失敗,並出現DirectoryNotFoundException。 有問題的方法是:

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。 當時,通過更改代理類對公眾的可見性來解決此問題。

我意識到帶有路徑的東西可能隱藏了實際的問題,但是我只是不知道下一步該怎么看。

編輯:這是第一個問題的堆棧跟蹤

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,這是構造函數:

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中的語句):

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]));
    }
}

在學習中心中通過此方法調用該方法:

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);
    }
}

依次由該方法調用(在圓的構造函數中調用):

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的子類。 另外,對文本牆感到抱歉,但我不知所措。

使用System.IO.Path.Combine()連接路徑部分。 例如:

代替 :

FileStream(path + _learningFolder + "\\Ratios.csv")

采用 :

FileStream(Path.Combine(Path.Combine(path , _learningFolder) , "Ratios.csv"))

只是不要忘記從每個部分中刪除\\\\。 並對其他FileStream路徑執行相同操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM