我有两个类(房间,出口),我认为应该相互依赖,但这会导致循环依赖,这是一个不好的事情,从我的阅读。
//problem
public class Game
{
public List<Room> Rooms {get; set;}
}
public class Room
{
public Exit Exit {get; set;}
}
public class Exit
{
public Room NextRoom {get; set;}
}
//Here is my solution
public class Game
{
public List<Room> Rooms {get; set;}
public Room GetNextRoom(Exit exit)
{
//Loops through the rooms list and compares Room.Id by Exit.NextRoomId and returns it
}
}
public class Room
{
public Exit Exit {get; set;}
}
public class Exit
{
public string NextRoomId {get;set;}
}我的问题是,我的解决办法是否有点正确,还是有更好的解决办法来解决这个问题。这打破了循环依赖关系,但在声明Exit对象时,它变得很难看,因为它通过字符串“引用”Room对象。
请记住,我不想实现一个接口或Eventhandler,我所读到的基本上只是一个创可贴的问题,并可能导致问题在未来。
发布于 2022-10-18 13:39:13
您所拥有的实际上是一个具有圈的有向图。你的模型是正确的-你不能摆脱周期。
但是,您不需要一个单独的“退出”类--您可以用一个名为(例如) List<Room>的Exits属性来表示每个房间的出口。
旁白:由于出口实际上是“定向”的(即它们只指向下一个房间),以表示第1室和第2室之间的双向出口,因此必须单独添加每个出口。也就是说,在增加一个从1号房间到2号房间的出口时,你也必须增加一个从2号房间到1号房间的出口(当然,除非出口是单向的)。
您可以使用Newtonsoft.Json来序列化和反序列化这样的图表,同时考虑循环引用。
关键是您需要指定Json序列化选项PreserveReferencesHandling = PreserveReferencesHandling.All。
另一个重要的事实是,您不能使用任何构造函数来设置类的属性,否则序列化/反序列化将失败。
这里有一个可编译的控制台应用程序来演示如何正确地完成它:
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace ConsoleApp1
{
static class Program
{
public static void Main()
{
var room1 = new Room { Name = "room1" };
var room2 = new Room { Name = "room2" };
var room3 = new Room { Name = "room3" };
room1.Exits.Add(room2); room2.Exits.Add(room1);
room2.Exits.Add(room3); room3.Exits.Add(room2);
room3.Exits.Add(room1); room1.Exits.Add(room3);
var jsonSettings = new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.Objects
};
var serialised = JsonConvert.SerializeObject(room1, jsonSettings);
var deserialised = JsonConvert.DeserializeObject<Room>(serialised, jsonSettings)!;
Console.WriteLine(deserialised.Name); // "room1"
Console.WriteLine(deserialised.Exits[0].Name); // "room2"
Console.WriteLine(deserialised.Exits[0].Exits[1].Name); // "room3"
}
}
public sealed class Room
{
public string Name { get; init; }
public List<Room> Exits { get; } = new ();
}
}请注意,"room3“之外的打印使用Exits[1],因为这是最初连接的方式。
发布于 2022-10-18 13:29:49
如果一个出口没有其他属性或者任何房间没有的属性(我不知道为什么一个出口会和一个房间不同,因为出口只是一个指向下一个房间的指针,或者如果你在游戏结束时是空的),那么我就会这样做,在这个房间里有一个引用下一个房间的引用。注意:这假设一个房间只有一个出口,如果有多个见mathews答案。
public class Game
{
public List<Room> Rooms { get; set; }
}
public class Room
{
public int RoomNumber { get; set; }
public Room Exit { get; set; }
}然后你可以像这样使用它
static void Main(string[] args)
{
Game game = new Game();
game.Rooms = new List<Room>();
Room firstRoom = new Room();
Room exit = new Room();
firstRoom.RoomNumber = 1;
exit.RoomNumber = 2;
firstRoom.Exit = exit;
game.Rooms.Add(firstRoom);
foreach(Room room in game.Rooms)
{
Console.WriteLine("Room:" + room.RoomNumber);
Console.WriteLine("Exit:" + room.Exit.RoomNumber);
}
Console.ReadKey();
}https://stackoverflow.com/questions/74111249
复制相似问题