我正在为Unity开发一个Item系统,我正试图推理XML文件操作。我有一个ItemDatabase类,如下所示:
[XmlRoot("ItemDatabase")]
public class ItemDatabase
{
// List that contains all Game Items.
// Members must be Serializable. Use Editor workflow
// to create an item Adder/Remover for the Database.
[XmlArray("Items"), XmlArrayItem("BaseGameItem")]
public List<BaseGameItem> Items = new List<BaseGameItem>();
// Singleton Pattern. Only one instance will be initialized.
public static ItemDatabase itemDb;
public ItemDatabase()
{
if(itemDb == null)
itemDb = this;
}
// Saves the Item List to an XML file.
public void Save(string filepath)
{
XmlSerializer serializer = new XmlSerializer(typeof(ItemDatabase));
// Disposable Pattern
using (FileStream stream = new FileStream(filepath, FileMode.Create))
{
// Check if path was valid.
if (stream != null)
{
serializer.Serialize(stream, this);
stream.Close();
}
}
}
// Loads an existing Item List from an XML file.
public static ItemDatabase Load(string filepath)
{
XmlSerializer serializer = new XmlSerializer(typeof(ItemDatabase));
using (FileStream stream = new FileStream(filepath, FileMode.Open))
{
if (stream != null)
{
ItemDatabase db = serializer.Deserialize(stream) as ItemDatabase;
stream.Close();
return db;
}
// Return null if the file cannot be read/found.
else
{
return null;
}
}
}
}
最近,我接触到了Singleton模式的一个非常基本的实现,这对我来说有意义用于像数据库这样的东西。该类的实例是静态的,而List在上面初始化。
然而,我尝试使用名为DatabaseManager类的GUI访问此类。相关实施如下所示:
public class ItemDatabaseManager : EditorWindow
{
// List of items from database.
List<BaseGameItem> items;
// Item template to add/remove from database.
// To be filled by user.
BaseGameItem itemToAdd;
private void OnEnable()
{
items = ItemDatabase.itemDb.Items;
}
我的思维过程让我相信:
但是,每当编辑器窗口出现时,我都会得到一个Null Reference Exception,表明项目列表为空。我已经确认它不是ItemDatabase实例。当List作为类定义的一部分立即初始化时,它怎么可能是空的?在这种情况下,我从根本上忽略了什么?也许我误解了构造函数的基本顺序?
假设我正确理解了事情,将列表设置为公共静态修复 - 但它违背了保持列表不可访问的目的?
答案 0 :(得分:1)
实际上,您没有正确实现单例模式,因为您在构造函数中创建了实例。 看看this MSDN article。
示例:
public class ItemDatabase
{
private static ItemDatabase _instance;
private ItemDatabase() {}
public static ItemDatabase Instance
{
get
{
if (instance == null)
{
instance = new ItemDatabase();
}
return instance;
}
}
// ... add the rest of your code
}
您现在可以通过以下方式访问单身人士:
ItemDatabase.Instance
,实例将在第一次访问时按需动态创建。
编辑:根据@maccettura评论,上面的代码是不线程安全。如果您需要线程安全,可以使用锁定对象(see this article for more info):
public class ItemDatabase
{
private static ItemDatabase _instance;
private static readonly object _lock = new object();
private ItemDatabase() {}
public static ItemDatabase Instance
{
get
{
lock (_object)
{
if (instance == null)
{
instance = new ItemDatabase();
}
return instance;
}
}
}
// ... add the rest of your code
}