On Windows Store apps (Metro apps), method signatures that received a full path to a file/folder were discarded, as Metro apps can alter only specific directories, exclusive to the application. For this reason, XDocument.Save cannot receive a string for a path anymore, and must instead receive a Stream. You must open a stream to the target file (the one where you want to write) using the new API, and then call Save with that file stream as argument.
The problem with the new API is that it requires the use of complicated async calls, and that eventually one method must wait for the result of the async “get write stream” operation (in this case), as the rest of the Unity game is not async (unless you want to convert large portions of code to use the async capabilites in Windows Metro only).
This example writes an XDocument to a file, using the new API (it also shows the old code to Save an XDocument with the full string path).
private void someMethodThatSavesXDocument()
{
XDocument doc = new XDocument(
new XElement("example",
new XElement("name", "John"),
new XElement("language", "en")
)
);
#if !NETFX_CORE
// active when NOT building for Windows Store apps
string fullPath = Application.persistentDataPath + "/folder/file.txt";
doc.Save(fullPath);
#else
// active when building for Windows Store apps
using (Stream stream = GetWriteStream("folder/file.txt"))
{
doc.Save(stream);
}
#endif
}
#if NETFX_CORE
// calls and waits for the completion of the method that uses the new async API
public static Stream GetWriteStream(string relativePath)
{
// In Unity games for the Windows Store, Application.persistentDataPath
// points to the same place as this ApplicationData.Current.LocalFolder
return getWriteStream(ApplicationData.Current.LocalFolder, relativePath).Result;
}
// async method that navigates to the file and opens it in write mode
private static async Task<Stream> getWriteStream(StorageFolder folder, string relativePath)
{
string name = Path.GetFileName(relativePath);
string dir = Path.GetDirectoryName(relativePath);
// get intermediate folders to file
string[] dirNames = dir.Split(new char[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
// navigate to last folder in relative path
foreach (string dirName in dirNames) {
folder = await folder.GetFolderAsync(dirName);
}
// create file and open stream to it
StorageFile file = await folder.CreateFileAsync(name, CreationCollisionOption.ReplaceExisting);
return await file.OpenStreamForWriteAsync();
}
#endif
Necessary includes for the new API in this example:
#if NETFX_CORE
using System;
using System.Threading.Tasks;
using Windows.Storage;
#endif
Please note that this example is only based on existing code of mine, but I haven’t tested it as it is. If you find errors please notify me. Also, you should avoid having those duplicated classes that you describe in the question by removing the unnecessary dlls.
Shameless plug: I also created a plugin to abstract the new API regarding IO in the Application.persistentDataPath folder, With it, you can simply call a method for some File/Directory operation, and it handles the new API internally. See the forum post for the asset here and the Asset Store link here.