/// <summary> /// Reloads an asset. If possible, same recursively referenced objects are reused. /// </summary> /// <param name="obj">The object.</param> /// <param name="settings">The settings.</param> /// <returns>True if it could be reloaded, false otherwise.</returns> /// <exception cref="System.InvalidOperationException">Asset not loaded through this AssetManager.</exception> public bool Reload(object obj, AssetManagerLoaderSettings settings = null) { if (settings == null) { settings = AssetManagerLoaderSettings.Default; } lock (LoadedAssetUrls) { AssetReference assetReference; if (!LoadedAssetReferences.TryGetValue(obj, out assetReference)) { return(false); } var url = assetReference.Url; using (var profile = Profiler.Begin(AssetProfilingKeys.AssetReload, url)) { DeserializeObject(url, obj.GetType(), obj, settings); } return(true); } }
private object DeserializeObject(string url, Type type, object obj, AssetManagerLoaderSettings settings) { var serializeOperations = new Queue <DeserializeOperation>(); serializeOperations.Enqueue(new DeserializeOperation(null, url, type, obj)); AssetReference reference = null; if (obj != null) { reference = FindDeserializedObject(url, type); if (reference.Object != obj) { throw new InvalidOperationException("Object doesn't match, can't reload"); } } // Let's put aside old references, so that we unload them only afterwise (avoid a referenced object to be unloaded for no reason) HashSet <AssetReference> references = null; if (reference != null) { // Let's collect dependent reference, and reset current list references = reference.References; reference.References = new HashSet <AssetReference>(); // Mark object as not deserialized yet reference.Deserialized = false; } bool isFirstOperation = true; object result = null; while (serializeOperations.Count > 0) { var serializeOperation = serializeOperations.Dequeue(); var deserializedObject = DeserializeObject(serializeOperations, serializeOperation.ParentAssetReference, serializeOperation.Url, serializeOperation.ObjectType, serializeOperation.Object, settings); if (isFirstOperation) { result = deserializedObject; isFirstOperation = false; } } if (reference != null) { foreach (var dependentReference in references) { DecrementReference(dependentReference, false); } } return(result); }
internal object DeserializeObjectRecursive(AssetReference parentAssetReference, out AssetReference assetReference, string url, Type objType, AssetManagerLoaderSettings settings, ContentSerializerContext otherContext, Stream stream, Type headerObjType, ConverterContext converterContext = null) { // Resolve URL ObjectId objectId; if (!FileProvider.AssetIndexMap.TryGetValue(url, out objectId)) { throw new InvalidOperationException(string.Format("Asset [{0}] not found.", url)); } // Find serializer var serializer = Serializer.GetSerializer(headerObjType, objType); if (serializer == null) { throw new InvalidOperationException(string.Format("Content serializer for {0}/{1} could not be found.", headerObjType, objType)); } var contentSerializerContext = new ContentSerializerContext(url, ArchiveMode.Deserialize, this); contentSerializerContext.chunkReferences.AddRange(otherContext.chunkReferences); // Create AssetReference assetReference = new AssetReference(objectId, url, parentAssetReference == null); contentSerializerContext.AssetReference = assetReference; var result = serializer.Construct(contentSerializerContext); var streamReader = new BinarySerializationReader(stream); PrepareSerializerContext(contentSerializerContext, streamReader.Context); contentSerializerContext.ConverterContext = converterContext; result = contentSerializerContext.SerializeContent(streamReader, serializer, result); SetAssetObject(assetReference, result); // Add reference if (parentAssetReference != null) { parentAssetReference.References.Add(assetReference); } return(result); }
/// <summary> /// Loads an asset from the specified URL. /// </summary> /// <param name="type">The type.</param> /// <param name="url">The URL.</param> /// <param name="settings">The settings.</param> /// <returns></returns> /// <exception cref="System.ArgumentNullException">url</exception> public object Load(Type type, string url, AssetManagerLoaderSettings settings = null) { if (settings == null) { settings = AssetManagerLoaderSettings.Default; } if (url == null) { throw new ArgumentNullException("url"); } lock (LoadedAssetUrls) { using (var profile = Profiler.Begin(AssetProfilingKeys.AssetLoad, url)) { return(DeserializeObject(url, type, null, settings)); } } }
public T Load <T>(string url, AssetManagerLoaderSettings settings = null) where T : class { if (settings == null) { settings = AssetManagerLoaderSettings.Default; } if (url == null) { throw new ArgumentNullException("url"); } lock (loadedAssetsByUrl) { using (var profile = Profiler.Begin(AssetProfilingKeys.AssetLoad, url)) { AssetReference assetReference; return((T)DeserializeObject(null, out assetReference, url, typeof(T), settings)); } } }
private object DeserializeObject(Queue <DeserializeOperation> serializeOperations, AssetReference parentAssetReference, string url, Type objType, object obj, AssetManagerLoaderSettings settings) { // Try to find already loaded object AssetReference assetReference = FindDeserializedObject(url, objType); if (assetReference != null && assetReference.Deserialized) { // Add reference bool isRoot = parentAssetReference == null; if (isRoot || parentAssetReference.References.Add(assetReference)) { IncrementReference(assetReference, isRoot); } return(assetReference.Object); } if (!FileProvider.FileExists(url)) { HandleAssetNotFound(url); return(null); } ContentSerializerContext contentSerializerContext; object result; // Open asset binary stream using (var stream = FileProvider.OpenStream(url, VirtualFileMode.Open, VirtualFileAccess.Read)) { // File does not exist // TODO/Benlitz: Add a log entry for that, it's not expected to happen if (stream == null) { return(null); } Type headerObjType = null; // Read header var streamReader = new BinarySerializationReader(stream); var chunkHeader = ChunkHeader.Read(streamReader); if (chunkHeader != null) { headerObjType = Type.GetType(chunkHeader.Type); } // Find serializer var serializer = Serializer.GetSerializer(headerObjType, objType); if (serializer == null) { throw new InvalidOperationException(string.Format("Content serializer for {0}/{1} could not be found.", headerObjType, objType)); } contentSerializerContext = new ContentSerializerContext(url, ArchiveMode.Deserialize, this) { LoadContentReferences = settings.LoadContentReferences }; // Read chunk references if (chunkHeader != null && chunkHeader.OffsetToReferences != -1) { // Seek to where references are stored and deserialize them streamReader.NativeStream.Seek(chunkHeader.OffsetToReferences, SeekOrigin.Begin); contentSerializerContext.SerializeReferences(streamReader); streamReader.NativeStream.Seek(chunkHeader.OffsetToObject, SeekOrigin.Begin); } if (assetReference == null) { // Create AssetReference assetReference = new AssetReference(url, parentAssetReference == null); contentSerializerContext.AssetReference = assetReference; result = obj ?? serializer.Construct(contentSerializerContext); SetAssetObject(assetReference, result); } else { result = assetReference.Object; contentSerializerContext.AssetReference = assetReference; } assetReference.Deserialized = true; PrepareSerializerContext(contentSerializerContext, streamReader.Context); contentSerializerContext.SerializeContent(streamReader, serializer, result); // Add reference if (parentAssetReference != null) { parentAssetReference.References.Add(assetReference); } } if (settings.LoadContentReferences) { // Process content references // TODO: Should we work at ChunkReference level? foreach (var contentReference in contentSerializerContext.ContentReferences) { bool shouldBeLoaded = true; //AssetReference childReference; if (settings.ContentFilter != null) { settings.ContentFilter(contentReference, ref shouldBeLoaded); } if (shouldBeLoaded) { serializeOperations.Enqueue(new DeserializeOperation(assetReference, contentReference.Location, contentReference.Type, contentReference.ObjectValue)); } } } return(result); }
/// <summary> /// Loads an asset from the specified URL asynchronously. /// </summary> /// <param name="type">The type.</param> /// <param name="url">The URL.</param> /// <param name="settings">The settings.</param> /// <returns></returns> public Task <object> LoadAsync(Type type, string url, AssetManagerLoaderSettings settings = null) { return(Task.Factory.StartNew(() => Load(type, url, settings))); }
/// <summary> /// Loads an asset from the specified URL asynchronously. /// </summary> /// <typeparam name="T">The content type.</typeparam> /// <param name="url">The URL to load from.</param> /// <param name="settings">The settings. If null, fallback to <see cref="AssetManagerLoaderSettings.Default" />.</param> /// <returns></returns> public Task <T> LoadAsync <T>(string url, AssetManagerLoaderSettings settings = null) where T : class { return(Task.Factory.StartNew(() => Load <T>(url, settings))); }
/// <summary> /// Loads an asset from the specified URL. /// </summary> /// <typeparam name="T">The content type.</typeparam> /// <param name="url">The URL to load from.</param> /// <param name="settings">The settings. If null, fallback to <see cref="AssetManagerLoaderSettings.Default" />.</param> /// <returns></returns> public T Load <T>(string url, AssetManagerLoaderSettings settings = null) where T : class { return((T)Load(typeof(T), url, settings)); }
internal object DeserializeObject(AssetReference parentAssetReference, out AssetReference assetReference, string url, Type objType, AssetManagerLoaderSettings settings, ConverterContext converterContext = null) { // Resolve URL ObjectId objectId; if (!FileProvider.AssetIndexMap.TryGetValue(url, out objectId)) { throw new InvalidOperationException(string.Format("Asset [{0}] not found.", url)); } // Try to find already loaded object if (loadedAssetsByUrl.TryGetValue(objectId, out assetReference)) { while (assetReference != null && !objType.GetTypeInfo().IsAssignableFrom(assetReference.Object.GetType().GetTypeInfo())) { assetReference = assetReference.Next; } if (assetReference != null) { // Add reference bool isRoot = parentAssetReference == null; if (isRoot || parentAssetReference.References.Add(assetReference)) { IncrementReference(assetReference, isRoot); } return(assetReference.Object); } } if (!FileProvider.FileExists(url)) { throw new InvalidOperationException(string.Format("Asset [{0}] not found.", url)); } ContentSerializerContext contentSerializerContext; object result; // Open asset binary stream using (var stream = FileProvider.OpenStream(url, VirtualFileMode.Open, VirtualFileAccess.Read)) { // File does not exist // TODO/Benlitz: Add a log entry for that, it's not expected to happen if (stream == null) { return(null); } Type headerObjType = null; // Read header var streamReader = new BinarySerializationReader(stream); var chunkHeader = ChunkHeader.Read(streamReader); if (chunkHeader != null) { headerObjType = Type.GetType(chunkHeader.Type); } // Find serializer var serializer = Serializer.GetSerializer(headerObjType, objType); if (serializer == null) { throw new InvalidOperationException(string.Format("Content serializer for {0}/{1} could not be found.", headerObjType, objType)); } contentSerializerContext = new ContentSerializerContext(url, ArchiveMode.Deserialize, this); // Read chunk references if (chunkHeader != null && chunkHeader.OffsetToReferences != -1) { // Seek to where references are stored and deserialize them streamReader.NativeStream.Seek(chunkHeader.OffsetToReferences, SeekOrigin.Begin); contentSerializerContext.SerializeReferences(streamReader); streamReader.NativeStream.Seek(chunkHeader.OffsetToObject, SeekOrigin.Begin); } // Create AssetReference assetReference = new AssetReference(objectId, url, parentAssetReference == null); contentSerializerContext.AssetReference = assetReference; result = serializer.Construct(contentSerializerContext); PrepareSerializerContext(contentSerializerContext, streamReader.Context); contentSerializerContext.ConverterContext = converterContext; result = contentSerializerContext.SerializeContent(streamReader, serializer, result); SetAssetObject(assetReference, result); // Add reference if (parentAssetReference != null) { parentAssetReference.References.Add(assetReference); } } if (settings.LoadContentReferences) { // Process content references // TODO: Should we work at ChunkReference level? foreach (var contentReference in contentSerializerContext.ContentReferences) { bool shouldBeLoaded = true; AssetReference childReference; if (settings.ContentFilter != null) { settings.ContentFilter(contentReference, ref shouldBeLoaded); } if (shouldBeLoaded) { contentReference.ObjectValue = DeserializeObject(assetReference, out childReference, contentReference.Location, contentReference.Type, settings); } } } return(result); }