public static DataContext CreateContext(IDataFileProvider dataFileProvider) { // Look for classes that extend DataContext var types = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsSubclassOf(typeof(DataContext))); foreach (var type in types) { // having attribute DataContextAttribute var dataContextAttribute = (DataContextAttribute)type.GetCustomAttributes(typeof(DataContextAttribute), false).FirstOrDefault(); if (dataContextAttribute != null) { DataContext context = (DataContext)Activator.CreateInstance(type); // Look for plugin specified by the attribute if (dataFileProvider.GetDataFile(FileMode.Open, dataContextAttribute.PluginFileName).Exists() && dataFileProvider.DataFolderPath.Contains(context.GetGameInstallPath())) { // Pass data provider to the context context.DataFileProvider = dataFileProvider; return(context); } } } throw new InvalidDataException("Unable to determine a suitable data context."); }
/// <summary> /// Copies a stream into the current data file, optionally only if does not exists and contains different data. /// </summary> /// <param name="input">The Stream to copy data from.</param> /// <param name="updateOnly">If true, file will not be recreated if already exists and contains the same data.</param> /// <returns>Returns true if file has been created or updated.</returns> public bool CopyFrom(Stream input, bool updateOnly) { if (mode == FileMode.Open) { throw new InvalidOperationException("Cannot write into data file retrieved using the FileMode.Open mode."); } // Non-data files such as plugin.txt do not have a request path relative to the data folder // TODO: Do not provide non-data files via DataFileProvider if (RequestedPath == null) { throw new InvalidOperationException("Cannot write into a special data file."); } if (updateOnly) { // Look if file already exists // To check whether it needs to be updated // Retreive new file from the provider with FileMode.Open var existingFile = provider.GetDataFile(FileMode.Open, RequestedPath); if (existingFile.Exists()) { using (var existingStream = existingFile.Open()) { // If input is not memory stream, create one and copy the data from the input stream into it MemoryStream memoryStream = input as MemoryStream; if (memoryStream == null) { // Initialize memory stream as big as the existing stream length if imput steam is not seekable int initialMemoryStreamLength = input.CanSeek ? (int)input.Length : (int)existingStream.Length; memoryStream = new MemoryStream(initialMemoryStreamLength); input.CopyTo(memoryStream); memoryStream.Position = 0; } // Compare existing stream with input stream (or memory stream where input stream was copied into) if (StreamComparer.Compare(existingStream, memoryStream)) { Log.Fine("Cached file {0} is up to date.", existingFile.FullPath); return(false); } // Reset memeory stream after comparison memoryStream.Position = 0; // Use memory stream (where input stream has been copied into) instead of input stream // when updating existing file if (input != memoryStream) { input = memoryStream; } Log.Fine("Cached file {0} exists but is no longer valid and will be updated.", existingFile.FullPath); } } else { Log.Fine("File {0} is not cached and will be created.", existingFile.FullPath); } } using (var newStream = Open()) { input.CopyTo(newStream); } return(true); }