/// <summary> /// Gets a type from its <see cref="DataContractAttribute.Alias"/> or <see cref="DataAliasAttribute.Name"/>. /// </summary> /// <param name="alias"></param> /// <returns></returns> public static Type GetTypeFromAlias(string alias) { // TODO: At some point we might want to reorganize AssemblyRegistry and DataSerializerFactory // I am not sure the list of assemblies matches between those two (some assemblies are probably not registered in AssemblyRegistry), // so the semantic of GetTypeFromAlias (which include all assemblies) might be different than GetType. return(DataSerializerFactory.GetTypeFromAlias(alias)); }
private static void UnloadAssemblies(ILogger log, AssemblyContainer assemblyContainer, List <ReloadedAssembly> loadedAssemblies) { for (int index = loadedAssemblies.Count - 1; index >= 0; index--) { var loadedAssembly = loadedAssemblies[index]; var assembly = loadedAssembly.PackageLoadedAssembly.Assembly; // Already unloaded or never loaded? if (assembly == null) { continue; } log?.Info($"Unloading assembly {assembly}"); // Unregisters assemblies that have been registered in Package.Load => Package.LoadAssemblyReferencesForPackage AssemblyRegistry.Unregister(assembly); // Unload binary serialization DataSerializerFactory.UnregisterSerializationAssembly(assembly); // Unload assembly assemblyContainer.UnloadAssembly(assembly); loadedAssembly.PackageLoadedAssembly.Assembly = null; } }
private static void LoadAssemblies(ILogger log, AssemblyContainer assemblyContainer, List <ReloadedAssembly> loadedAssemblies, bool newVersion, bool firstTime) { foreach (var loadedAssembly in loadedAssemblies) { loadedAssembly.PackageLoadedAssembly.Path = newVersion ? loadedAssembly.NewAssemblyPath : loadedAssembly.OldAssemblyPath; Assembly assembly = null; try { // If first time, load assembly if (firstTime) { loadedAssembly.NewAssembly = assemblyContainer.LoadAssemblyFromPath(loadedAssembly.PackageLoadedAssembly.Path); } // Load assembly assembly = newVersion ? loadedAssembly.NewAssembly : loadedAssembly.OriginalAssembly; log?.Info($"Loading assembly {assembly}"); loadedAssembly.PackageLoadedAssembly.Assembly = assembly; // Unregisters assemblies that have been registered in Package.Load => Package.LoadAssemblyReferencesForPackage AssemblyRegistry.Register(assembly, AssemblyCommonCategories.Assets); DataSerializerFactory.RegisterSerializationAssembly(assembly); } catch (Exception e) { log?.Error($"Error loading assembly {assembly?.ToString() ?? Path.GetFileNameWithoutExtension(loadedAssembly.PackageLoadedAssembly.Path)}: ", e); } } }
internal static void Initialize() { var assemblySerializers = new AssemblySerializers(typeof(StrategySerializerFactory).GetTypeInfo().Assembly); // Register data contract aliases assemblySerializers.Modules.Add(typeof(SiliconStudio.DataSerializers.SiliconStudio_Xenko_EngineSerializerFactory).GetTypeInfo().Module); assemblySerializers.Modules.Add(typeof(SiliconStudio.DataSerializers.Strategy_GameSerializerFactory).GetTypeInfo().Module); assemblySerializers.Modules.Add(typeof(SiliconStudio.DataSerializers.SiliconStudio_Xenko_PhysicsSerializerFactory).GetTypeInfo().Module); assemblySerializers.Modules.Add(typeof(SiliconStudio.DataSerializers.SiliconStudio_Xenko_ParticlesSerializerFactory).GetTypeInfo().Module); assemblySerializers.Modules.Add(typeof(SiliconStudio.DataSerializers.SiliconStudio_Xenko_SpriteStudio_RuntimeSerializerFactory).GetTypeInfo().Module); assemblySerializers.Modules.Add(typeof(SiliconStudio.DataSerializers.SiliconStudio_Xenko_NativeSerializerFactory).GetTypeInfo().Module); assemblySerializers.Modules.Add(typeof(SiliconStudio.DataSerializers.SiliconStudio_Xenko_UISerializerFactory).GetTypeInfo().Module); { var assemblySerializersProfile = new AssemblySerializersPerProfile(); assemblySerializers.Profiles["Default"] = assemblySerializersProfile; } { var assemblySerializersProfile = new AssemblySerializersPerProfile(); assemblySerializers.Profiles["Content"] = assemblySerializersProfile; } { var assemblySerializersProfile = new AssemblySerializersPerProfile(); assemblySerializers.Profiles["Hash"] = assemblySerializersProfile; } { var assemblySerializersProfile = new AssemblySerializersPerProfile(); assemblySerializers.Profiles["Clone"] = assemblySerializersProfile; } DataSerializerFactory.RegisterSerializationAssembly(assemblySerializers); AssemblyRegistry.Register(typeof(StrategySerializerFactory).GetTypeInfo().Assembly, AssemblyCommonCategories.Engine); }
internal static void Initialize() { var assemblySerializers = new AssemblySerializers(typeof(Strategy_GameSerializerFactory).GetTypeInfo().Assembly); // Register data contract aliases assemblySerializers.Modules.Add(typeof(SiliconStudio.DataSerializers.SiliconStudio_Xenko_EngineSerializerFactory).GetTypeInfo().Module); assemblySerializers.Modules.Add(typeof(SiliconStudio.DataSerializers.SiliconStudio_Core_MathematicsSerializerFactory).GetTypeInfo().Module); assemblySerializers.Modules.Add(typeof(SiliconStudio.DataSerializers.SiliconStudio_CoreSerializerFactory).GetTypeInfo().Module); assemblySerializers.Modules.Add(typeof(SiliconStudio.DataSerializers.SiliconStudio_Xenko_PhysicsSerializerFactory).GetTypeInfo().Module); assemblySerializers.Modules.Add(typeof(SiliconStudio.DataSerializers.SiliconStudio_Xenko_ParticlesSerializerFactory).GetTypeInfo().Module); assemblySerializers.Modules.Add(typeof(SiliconStudio.DataSerializers.SiliconStudio_Xenko_SpriteStudio_RuntimeSerializerFactory).GetTypeInfo().Module); assemblySerializers.Modules.Add(typeof(SiliconStudio.DataSerializers.SiliconStudio_Xenko_NativeSerializerFactory).GetTypeInfo().Module); assemblySerializers.Modules.Add(typeof(SiliconStudio.DataSerializers.SiliconStudio_Xenko_UISerializerFactory).GetTypeInfo().Module); { var assemblySerializersProfile = new AssemblySerializersPerProfile(); assemblySerializers.Profiles["Default"] = assemblySerializersProfile; assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0x8ecbed72, 0x29961d9f, 0x7617bcde, 0x48ddcbbf), typeof(Strategy.BasicCameraController), typeof(SiliconStudio.DataSerializers.Strategy_BasicCameraControllerSerializer))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0xda9eedc9, 0x763b3754, 0x1aba0f49, 0xfd437b97), typeof(Strategy.Believe), typeof(SiliconStudio.DataSerializers.Strategy_BelieveSerializer))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0x65a63635, 0x905b96ce, 0x5fa716d9, 0x67302976), typeof(Strategy.City), typeof(SiliconStudio.DataSerializers.Strategy_CitySerializer))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0xa6f677d0, 0x0f6a25c4, 0x56c1dbd7, 0x70d216a3), typeof(System.Collections.Generic.Dictionary <System.Int32, System.Int32>), typeof(SiliconStudio.Core.Serialization.Serializers.DictionarySerializer <System.Int32, System.Int32>))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0xdc943164, 0x20bcb78a, 0xf70ca33c, 0xf1fd3d6a), typeof(Strategy.City_Classification), typeof(SiliconStudio.DataSerializers.Strategy_City_ClassificationSerializer))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0xa93b8fcb, 0x9809c426, 0x3a89a217, 0x4b079f7c), typeof(Strategy.Country), typeof(SiliconStudio.DataSerializers.Strategy_CountrySerializer))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0x3e3ca2b8, 0x17007a32, 0xa8a3b32f, 0x26e7f933), typeof(System.Collections.Generic.List <System.Int32>), typeof(SiliconStudio.Core.Serialization.Serializers.ListSerializer <System.Int32>))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0xeeced12e, 0xe7cf9dbb, 0x418d7fb1, 0xb4736226), typeof(System.Collections.Generic.Dictionary <Strategy.Population, System.Int32>), typeof(SiliconStudio.Core.Serialization.Serializers.DictionarySerializer <Strategy.Population, System.Int32>))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0x6f744978, 0xf28745fb, 0x96b3d247, 0x06f11b9a), typeof(Strategy.Population), typeof(SiliconStudio.DataSerializers.Strategy_PopulationSerializer))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0x1e34102a, 0x1db28d8e, 0xad398cdc, 0x67d931a3), typeof(Strategy.Government), typeof(SiliconStudio.DataSerializers.Strategy_GovernmentSerializer))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0xeb366091, 0x8f13daa9, 0x2af6fed2, 0x2b70cd7b), typeof(System.Collections.Generic.List <Strategy.Government_Staff_Person>), typeof(SiliconStudio.Core.Serialization.Serializers.ListSerializer <Strategy.Government_Staff_Person>))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0x0f93cb0b, 0xd9c95143, 0x88fe7784, 0x38de8233), typeof(Strategy.Government_Staff_Person), typeof(SiliconStudio.DataSerializers.Strategy_Government_Staff_PersonSerializer))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0x1834c528, 0x4428c4d7, 0x80fbc09a, 0xb103d274), typeof(Strategy.Religion), typeof(SiliconStudio.DataSerializers.Strategy_ReligionSerializer))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0xec16c101, 0x148a775a, 0x4ab58eb2, 0x4c6bfa4d), typeof(Strategy.country_reign_form), typeof(SiliconStudio.DataSerializers.Strategy_country_reign_formSerializer))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0xe72963d9, 0x84002115, 0x9cf6d4cd, 0x3c378fd3), typeof(Strategy.Ethnicity), typeof(SiliconStudio.DataSerializers.Strategy_EthnicitySerializer))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0x1dfc486b, 0xd61bfe58, 0x4e0d571a, 0x2a4deabf), typeof(Strategy.GameManager), typeof(SiliconStudio.DataSerializers.Strategy_GameManagerSerializer))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0x736e9489, 0x057acd73, 0xf1f06ac1, 0x04cee503), typeof(System.Collections.Generic.Dictionary <System.Int32, Strategy.Population>), typeof(SiliconStudio.Core.Serialization.Serializers.DictionarySerializer <System.Int32, Strategy.Population>))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0x386b93ec, 0xb58c77bd, 0x7393c4df, 0xc5d84cf2), typeof(System.Collections.Generic.Dictionary <System.Int32, Strategy.Country>), typeof(SiliconStudio.Core.Serialization.Serializers.DictionarySerializer <System.Int32, Strategy.Country>))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0xdf6c3af2, 0x24e8bdaa, 0xa6f91ebf, 0x67389c06), typeof(System.Collections.Generic.Dictionary <System.Int32, Strategy.Believe>), typeof(SiliconStudio.Core.Serialization.Serializers.DictionarySerializer <System.Int32, Strategy.Believe>))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0x764a2b01, 0x498771de, 0xf8b11b3b, 0x4b0c00ff), typeof(System.Collections.Generic.Dictionary <System.Int32, Strategy.State>), typeof(SiliconStudio.Core.Serialization.Serializers.DictionarySerializer <System.Int32, Strategy.State>))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0xfb71cc71, 0xc716d0b7, 0x72b5948e, 0xb3c53064), typeof(Strategy.State), typeof(SiliconStudio.DataSerializers.Strategy_StateSerializer))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0xfb6b8fed, 0x28034bf3, 0x2c6d2465, 0xe27ec6fb), typeof(System.Collections.Generic.Dictionary <System.Int32, Strategy.Province>), typeof(SiliconStudio.Core.Serialization.Serializers.DictionarySerializer <System.Int32, Strategy.Province>))); assemblySerializersProfile.Add(new AssemblySerializerEntry(new SiliconStudio.Core.Storage.ObjectId(0x79983ce7, 0xa418e807, 0xd9b616f3, 0x6c9e7a2c), typeof(Strategy.Province), typeof(SiliconStudio.DataSerializers.Strategy_ProvinceSerializer))); } { var assemblySerializersProfile = new AssemblySerializersPerProfile(); assemblySerializers.Profiles["Content"] = assemblySerializersProfile; } { var assemblySerializersProfile = new AssemblySerializersPerProfile(); assemblySerializers.Profiles["Hash"] = assemblySerializersProfile; } { var assemblySerializersProfile = new AssemblySerializersPerProfile(); assemblySerializers.Profiles["Clone"] = assemblySerializersProfile; } DataSerializerFactory.RegisterSerializationAssembly(assemblySerializers); AssemblyRegistry.Register(typeof(Strategy_GameSerializerFactory).GetTypeInfo().Assembly, AssemblyCommonCategories.Engine); }
public void RegisterAssembly(Assembly assembly, IAttributeRegistry attributeRegistry) { if (assembly == null) { throw new ArgumentNullException(nameof(assembly)); } if (attributeRegistry == null) { throw new ArgumentNullException(nameof(attributeRegistry)); } // Add automatically the assembly for lookup if (!lookupAssemblies.Contains(assembly)) { lookupAssemblies.Add(assembly); // Register all tags automatically. var assemblySerializers = DataSerializerFactory.GetAssemblySerializers(assembly); if (assemblySerializers != null) { foreach (var dataContractAlias in assemblySerializers.DataContractAliases) { RegisterTagMapping(dataContractAlias.Name, dataContractAlias.Type, dataContractAlias.IsAlias); } } else { Log.Warning($"Assembly [{assembly}] has not been processed by assembly processor with --serialization flags. [DataContract] aliases won't be available."); } // Automatically register YamlSerializableFactory var assemblyScanTypes = AssemblyRegistry.GetScanTypes(assembly); if (assemblyScanTypes != null) { List <Type> types; // Register serializer factories if (assemblyScanTypes.Types.TryGetValue(typeof(IYamlSerializableFactory), out types)) { foreach (var type in types) { if (typeof(IYamlSerializableFactory).IsAssignableFrom(type) && type.GetConstructor(Type.EmptyTypes) != null) { try { SerializableFactories.Add((IYamlSerializableFactory)Activator.CreateInstance(type)); } catch { // Registrying an assembly should not fail, so we are silently discarding a factory if // we are not able to load it. } } } } } } }
public void NondataContractObject_ReturnsXmlSerializer() { //Arrange var factory = new DataSerializerFactory(); //Act var serializer = factory.GetSerializer<XmlTestClass>(); //Assert Assert.IsNotNull(serializer as XmlSerializer<XmlTestClass>, "failed to select XmlSerializer for non data contract"); }
public override UpdatableMember ResolveIndexer(string indexerName) { // Note: we currently only support component with data contract aliases var dotIndex = indexerName.LastIndexOf('.'); // TODO: Temporary hack to get static field of the requested type/property name // Need to have access to DataContract name<=>type mapping in the runtime (only accessible in SiliconStudio.Core.Design now) var typeName = (dotIndex == -1) ? indexerName : indexerName.Substring(0, dotIndex); var type = DataSerializerFactory.GetTypeFromAlias(typeName); if (type == null) { throw new InvalidOperationException($"Can't find a type with alias {typeName}; did you properly set a DataContractAttribute with this alias?"); } return(new EntityComponentPropertyAccessor(type)); }
public void Serialize(ContentSerializerContext context, SerializationStream stream, T obj) { // Get serializer // Note: Currently registered serializer is the content reference one // However, we would like to serialize the actual type here if (dataSerializer == null) { var dataSerializerType = DataSerializerFactory.GetSerializer("Default", typeof(T)).SerializerType; if (dataSerializerType == null) { throw new InvalidOperationException($"Could not find a serializer for type {typeof(T)}"); } dataSerializer = (DataSerializer <T>)Activator.CreateInstance(dataSerializerType); dataSerializer.Initialize(stream.Context.SerializerSelector); } // Serialize object stream.SerializeExtended(ref obj, context.Mode, dataSerializer); }
/// <summary> /// Compiles a list of update operations into a <see cref="CompiledUpdate"/>, for use with <see cref="Run"/>. /// </summary> /// <param name="rootObjectType">The type of the root object.</param> /// <param name="animationPaths">The different paths and source offsets to use when <see cref="Run"/> is applied.</param> /// <returns>A <see cref="CompiledUpdate"/> object that can be used for <see cref="Run"/>.</returns> public static CompiledUpdate Compile(Type rootObjectType, List <UpdateMemberInfo> animationPaths) { var currentPath = string.Empty; var temporaryObjectsList = new List <object>(); var state = new ComputeUpdateOperationState(); state.UpdateOperations = new List <UpdateOperation>(); state.StackPath = new List <AnimationBuilderStackEntry> { new AnimationBuilderStackEntry(rootObjectType, 0, 0, -1), }; foreach (var animationPath in animationPaths) { var commonPathParts = 1; // Detect how much of the path is unmodified (note: we start from 1 because root always stay there) for (int index = 1; index < state.StackPath.Count; index++) { var pathPart = state.StackPath[index]; // Check if next path part is the same (first check length then content) if (((animationPath.Name.Length == pathPart.EndIndex) || (animationPath.Name.Length > pathPart.EndIndex && (animationPath.Name[pathPart.EndIndex] == PathDelimiter || animationPath.Name[pathPart.EndIndex] == PathIndexerOpen))) && string.Compare(animationPath.Name, pathPart.StartIndex, currentPath, pathPart.StartIndex, pathPart.EndIndex - pathPart.StartIndex, StringComparison.Ordinal) == 0) { commonPathParts++; continue; } break; } PopObjects(ref state, commonPathParts); // Parse the new path parts state.ParseElementStart = state.StackPath.Last().EndIndex; // Compute offset from start of current object state.NewOffset = state.StackPath.Last().ObjectStartOffset; while (state.ParseElementStart < animationPath.Name.Length) { var containerType = state.StackPath.Last().Type; // We have only two cases for now: array or property/field name bool isIndexerAccess = animationPath.Name[state.ParseElementStart] == PathIndexerOpen; if (isIndexerAccess) { // Parse until end of indexer state.ParseElementEnd = animationPath.Name.IndexOf(PathIndexerClose, state.ParseElementStart + 1); if (state.ParseElementEnd == -1) { throw new InvalidOperationException("Property path parse error: could not find indexer end ']'"); } // Include the indexer close state.ParseElementEnd++; // Parse integer // TODO: Avoid substring? var indexerString = animationPath.Name.Substring(state.ParseElementStart + 1, state.ParseElementEnd - state.ParseElementStart - 2); // T[], IList<T>, etc... // Try to resolve using custom resolver UpdatableMember updatableMember = null; var parentType = containerType; while (parentType != null) { UpdateMemberResolver resolver; if (MemberResolvers.TryGetValue(parentType, out resolver)) { updatableMember = resolver.ResolveIndexer(indexerString); if (updatableMember != null) { break; } } parentType = parentType.GetTypeInfo().BaseType; } // Try interfaces if (updatableMember == null) { foreach (var implementedInterface in containerType.GetTypeInfo().ImplementedInterfaces) { UpdateMemberResolver resolver; if (MemberResolvers.TryGetValue(implementedInterface, out resolver)) { updatableMember = resolver.ResolveIndexer(indexerString); if (updatableMember != null) { break; } } } } if (updatableMember == null) { throw new InvalidOperationException(string.Format("Property path parse error: could not find binding info for index {0} in type {1}", indexerString, containerType)); } ProcessMember(ref state, animationPath, updatableMember, temporaryObjectsList); } else { // Note: first character might be a . delimiter, if so, skip it var propertyStart = state.ParseElementStart; if (animationPath.Name[propertyStart] == PathDelimiter) { propertyStart++; } // Check if it started with a parenthesis (to perform a cast operation) if (animationPath.Name[propertyStart] == PathCastOpen) { // Parse until end of cast operation state.ParseElementEnd = animationPath.Name.IndexOf(PathCastClose, ++propertyStart); if (state.ParseElementEnd == -1) { throw new InvalidOperationException("Property path parse error: could not find cast operation ending ')'"); } var typeName = animationPath.Name.Substring(propertyStart, state.ParseElementEnd - propertyStart); // Include the indexer close state.ParseElementEnd++; // Try to resolve using alias first, then full assembly registry using assembly qualified name var type = DataSerializerFactory.GetTypeFromAlias(typeName) ?? AssemblyRegistry.GetType(typeName); if (type == null) { throw new InvalidOperationException($"Could not resolve type {typeName}"); } // Push entry with new type // TODO: Should we actually perform an early castclass and skip if type is incorrect? state.StackPath.Add(new AnimationBuilderStackEntry(type, state.ParseElementStart, state.ParseElementEnd, -1) { ObjectStartOffset = state.NewOffset, }); } else { UpdatableMember updatableMember; // Parse until end next group (or end) state.ParseElementEnd = animationPath.Name.IndexOfAny(PathGroupDelimiters, state.ParseElementStart + 1); if (state.ParseElementEnd == -1) { state.ParseElementEnd = animationPath.Name.Length; } // TODO: Avoid substring? var propertyName = animationPath.Name.Substring(propertyStart, state.ParseElementEnd - propertyStart); if (!UpdateKeys.TryGetValue(new UpdateKey(containerType, propertyName), out updatableMember)) { // Try to resolve using custom resolver var parentType = containerType; while (parentType != null) { UpdateMemberResolver resolver; if (MemberResolvers.TryGetValue(parentType, out resolver)) { updatableMember = resolver.ResolveProperty(propertyName); if (updatableMember != null) { break; } } parentType = parentType.GetTypeInfo().BaseType; } if (updatableMember == null) { throw new InvalidOperationException(string.Format("Property path parse error: could not find binding info for member {0} in type {1}", propertyName, containerType)); } } // Process member ProcessMember(ref state, animationPath, updatableMember, temporaryObjectsList); } } state.ParseElementStart = state.ParseElementEnd; } currentPath = animationPath.Name; } // Totally pop the stack (we might still have stuff to copy back into properties PopObjects(ref state, 0); return(new CompiledUpdate { TemporaryObjects = temporaryObjectsList.ToArray(), UpdateOperations = state.UpdateOperations.ToArray(), }); }
public static void Reload(Game game, AssemblyContainer assemblyContainer, List <Assembly> assembliesToUnregister, List <Assembly> assembliesToRegister) { List <Entity> entities = new List <Entity>(); if (game != null) { entities.AddRange(game.SceneSystem.SceneInstance); } CloneReferenceSerializer.References = new List <object>(); var loadedAssembliesSet = new HashSet <Assembly>(assembliesToUnregister); var reloadedComponents = new List <ReloadedComponentEntryLive>(); throw new NotImplementedException("Need to reimplement this to use IUnloadable"); foreach (var assembly in assembliesToUnregister) { // Unregisters assemblies that have been registered in Package.Load => Package.LoadAssemblyReferencesForPackage AssemblyRegistry.Unregister(assembly); // Unload binary serialization DataSerializerFactory.UnregisterSerializationAssembly(assembly); // Unload assembly assemblyContainer.UnloadAssembly(assembly); } foreach (var assembly in assembliesToRegister) { ModuleRuntimeHelpers.RunModuleConstructor(assembly.ManifestModule); // Unregisters assemblies that have been registered in Package.Load => Package.LoadAssemblyReferencesForPackage AssemblyRegistry.Register(assembly, AssemblyCommonCategories.Assets); DataSerializerFactory.RegisterSerializationAssembly(assembly); } // First pass of deserialization: recreate the scripts foreach (ReloadedComponentEntryLive reloadedScript in reloadedComponents) { // Try to create object var objectStart = reloadedScript.YamlEvents.OfType <MappingStart>().FirstOrDefault(); if (objectStart != null) { // Get type info var objectStartTag = objectStart.Tag; bool alias; var componentType = AssetYamlSerializer.Default.GetSerializerSettings().TagTypeRegistry.TypeFromTag(objectStartTag, out alias); if (componentType != null) { reloadedScript.NewComponent = (EntityComponent)Activator.CreateInstance(componentType); } } } // Second pass: update script references in live objects // As a result, any script references processed by Yaml serializer will point to updated objects (script reference cycle will work!) for (int index = 0; index < CloneReferenceSerializer.References.Count; index++) { var component = CloneReferenceSerializer.References[index] as EntityComponent; if (component != null) { var reloadedComponent = reloadedComponents.FirstOrDefault(x => x.OriginalComponent == component); if (reloadedComponent != null) { CloneReferenceSerializer.References[index] = reloadedComponent.NewComponent; } } } // Third pass: deserialize reloadedComponents.ForEach(x => ReplaceComponent(game, x)); CloneReferenceSerializer.References = null; }
public static void Reload(Game game, AssemblyContainer assemblyContainer, List <Assembly> assembliesToUnregister, List <Assembly> assembliesToRegister) { List <Entity> entities = new List <Entity>(); if (game != null) { entities.AddRange(game.SceneSystem.SceneInstance); } CloneReferenceSerializer.References = new List <object>(); var loadedAssembliesSet = new HashSet <Assembly>(assembliesToUnregister); var reloadedComponents = new List <ReloadedComponentEntryLive>(); var componentsToReload = AssemblyReloader.CollectComponentsToReload(entities, loadedAssembliesSet); foreach (var componentToReload in componentsToReload) { var parsingEvents = SerializeComponent(componentToReload.Component); // TODO: Serialize Scene script too (async?) -- doesn't seem necessary even for complex cases // (i.e. referencing assets, entities and/or scripts) but still a ref counting check might be good reloadedComponents.Add(new ReloadedComponentEntryLive(componentToReload, parsingEvents)); } foreach (var assembly in assembliesToUnregister) { // Unregisters assemblies that have been registered in Package.Load => Package.LoadAssemblyReferencesForPackage AssemblyRegistry.Unregister(assembly); // Unload binary serialization DataSerializerFactory.UnregisterSerializationAssembly(assembly); // Unload assembly assemblyContainer.UnloadAssembly(assembly); } foreach (var assembly in assembliesToRegister) { ModuleRuntimeHelpers.RunModuleConstructor(assembly.ManifestModule); // Unregisters assemblies that have been registered in Package.Load => Package.LoadAssemblyReferencesForPackage AssemblyRegistry.Register(assembly, AssemblyCommonCategories.Assets); DataSerializerFactory.RegisterSerializationAssembly(assembly); } // First pass of deserialization: recreate the scripts foreach (ReloadedComponentEntryLive reloadedScript in reloadedComponents) { // Try to create object var objectStart = reloadedScript.YamlEvents.OfType <MappingStart>().FirstOrDefault(); if (objectStart != null) { // Get type info var objectStartTag = objectStart.Tag; bool alias; var componentType = YamlSerializer.GetSerializerSettings().TagTypeRegistry.TypeFromTag(objectStartTag, out alias); if (componentType != null) { reloadedScript.NewComponent = (EntityComponent)Activator.CreateInstance(componentType); } } } // Second pass: update script references in live objects // As a result, any script references processed by Yaml serializer will point to updated objects (script reference cycle will work!) for (int index = 0; index < CloneReferenceSerializer.References.Count; index++) { var component = CloneReferenceSerializer.References[index] as EntityComponent; if (component != null) { var reloadedComponent = reloadedComponents.FirstOrDefault(x => x.OriginalComponent == component); if (reloadedComponent != null) { CloneReferenceSerializer.References[index] = reloadedComponent.NewComponent; } } } // Third pass: deserialize reloadedComponents.ForEach(x => ReplaceComponent(game, x)); CloneReferenceSerializer.References = null; }
public void Reload() { CloneReferenceSerializer.References = new List <object>(); var loadedAssembliesSet = new HashSet <Assembly>(assembliesToUnregister); var reloadedScripts = CollectReloadedScriptEntries(loadedAssembliesSet); foreach (var assembly in assembliesToUnregister) { // Unregisters assemblies that have been registered in Package.Load => Package.LoadAssemblyReferencesForPackage AssemblyRegistry.Unregister(assembly); // Unload binary serialization DataSerializerFactory.UnregisterSerializationAssembly(assembly); // Unload assembly assemblyContainer.UnloadAssembly(assembly); } foreach (var assembly in assembliesToRegister) { ModuleRuntimeHelpers.RunModuleConstructor(assembly.ManifestModule); // Unregisters assemblies that have been registered in Package.Load => Package.LoadAssemblyReferencesForPackage AssemblyRegistry.Register(assembly, AssemblyCommonCategories.Assets); DataSerializerFactory.RegisterSerializationAssembly(assembly); } // First pass of deserialization: recreate the scripts foreach (ReloadedScriptEntryLive reloadedScript in reloadedScripts) { // Try to create object var objectStart = reloadedScript.YamlEvents.OfType <SharpYaml.Events.MappingStart>().FirstOrDefault(); if (objectStart != null) { // Get type info var objectStartTag = objectStart.Tag; bool alias; var scriptType = YamlSerializer.GetSerializerSettings().TagTypeRegistry.TypeFromTag(objectStartTag, out alias); if (scriptType != null) { reloadedScript.NewScript = (Script)Activator.CreateInstance(scriptType); } } } // Second pass: update script references in live objects // As a result, any script references processed by Yaml serializer will point to updated objects (script reference cycle will work!) for (int index = 0; index < CloneReferenceSerializer.References.Count; index++) { var script = CloneReferenceSerializer.References[index] as Script; if (script != null) { var reloadedScript = reloadedScripts.Cast <ReloadedScriptEntryLive>().FirstOrDefault(x => x.OriginalScript == script); if (reloadedScript != null) { CloneReferenceSerializer.References[index] = reloadedScript.NewScript; } } } // Third pass: deserialize RestoreReloadedScriptEntries(reloadedScripts); CloneReferenceSerializer.References = null; }