Ejemplo n.º 1
0
        private static void RegisterAssetAssembly(Assembly assembly)
        {
            if (assembly == null)
            {
                throw new ArgumentNullException(nameof(assembly));
            }

            lock (RegistryLock)
            {
                if (RegisteredAssetAssemblies.Contains(assembly))
                {
                    return;
                }

                RegisteredAssetAssemblies.Add(assembly);

                var assemblyScanTypes = AssemblyRegistry.GetScanTypes(assembly);
                if (assemblyScanTypes != null)
                {
                    List <Type> types;

                    var instantiatedObjects = new Dictionary <Type, object>();

                    // Register serializer factories
                    if (assemblyScanTypes.Types.TryGetValue(typeof(IYamlSerializableFactory), out types))
                    {
                        foreach (var type in types)
                        {
                            // Register serializer factories
                            if (!type.IsAbstract &&
                                type.GetCustomAttribute <YamlSerializerFactoryAttribute>() != null && type.GetConstructor(Type.EmptyTypes) != null)
                            {
                                try
                                {
                                    var instance = Activator.CreateInstance(type);
                                    instantiatedObjects.Add(type, instance);
                                    RegisteredSerializerFactories.Add((IYamlSerializableFactory)instance);
                                }
                                catch (Exception ex)
                                {
                                    Log.Error($"Unable to instantiate serializer factory [{type}]", ex);
                                }
                            }
                        }
                    }

                    // Custom visitors
                    if (assemblyScanTypes.Types.TryGetValue(typeof(IDataCustomVisitor), out types))
                    {
                        foreach (var type in types)
                        {
                            if (!type.IsAbstract && type.GetConstructor(Type.EmptyTypes) != null)
                            {
                                try
                                {
                                    object instance;
                                    if (!instantiatedObjects.TryGetValue(type, out instance))
                                    {
                                        instance = Activator.CreateInstance(type);
                                        instantiatedObjects.Add(type, instance);
                                    }
                                    RegisteredDataVisitNodes.Add((IDataCustomVisitor)instance);
                                }
                                catch (Exception ex)
                                {
                                    Log.Error($"Unable to instantiate custom visitor [{type}]", ex);
                                }
                            }
                        }
                    }

                    // Asset importer
                    if (assemblyScanTypes.Types.TryGetValue(typeof(IAssetImporter), out types))
                    {
                        foreach (var type in types)
                        {
                            if (!type.IsAbstract && type.GetConstructor(Type.EmptyTypes) != null)
                            {
                                try
                                {
                                    object instance;
                                    if (!instantiatedObjects.TryGetValue(type, out instance))
                                    {
                                        instance = Activator.CreateInstance(type);
                                        instantiatedObjects.Add(type, instance);
                                    }
                                    // Register the importer instance
                                    RegisterImporter((IAssetImporter)instance);
                                }
                                catch (Exception ex)
                                {
                                    Log.Error($"Unable to instantiate importer [{type.Name}]", ex);
                                }
                            }
                        }
                    }

                    // Register asset factory
                    if (assemblyScanTypes.Types.TryGetValue(typeof(IAssetFactory <>), out types))
                    {
                        foreach (var type in types)
                        {
                            if (!type.IsAbstract && !type.IsGenericTypeDefinition && type.GetConstructor(Type.EmptyTypes) != null)
                            {
                                object instance;
                                if (!instantiatedObjects.TryGetValue(type, out instance))
                                {
                                    instance = Activator.CreateInstance(type);
                                    instantiatedObjects.Add(type, instance);
                                }
                                RegisteredAssetFactories.Add(type.Name, (IAssetFactory <Asset>)instance);
                            }
                        }
                    }

                    // Package upgraders
                    if (assemblyScanTypes.Types.TryGetValue(typeof(PackageUpgraderAttribute), out types))
                    {
                        foreach (var type in types)
                        {
                            var packageUpgraderAttribute = type.GetCustomAttribute <PackageUpgraderAttribute>();
                            if (packageUpgraderAttribute != null)
                            {
                                try
                                {
                                    var packageUpgrader = (PackageUpgrader)Activator.CreateInstance(type);
                                    packageUpgrader.Attribute = packageUpgraderAttribute;
                                    RegisteredPackageUpgraders[packageUpgraderAttribute.PackageName] = packageUpgrader;
                                }
                                catch (Exception ex)
                                {
                                    Log.Error($"Unable to instantiate package upgrader [{type.Name}]", ex);
                                }
                            }
                        }
                    }

                    // Package analyzers
                    if (assemblyScanTypes.Types.TryGetValue(typeof(PackageSessionAnalysisBase), out types))
                    {
                        foreach (var type in types)
                        {
                            if (type.GetConstructor(Type.EmptyTypes) != null)
                            {
                                RegisteredPackageSessionAnalysisTypes.Add(type);
                            }
                        }
                    }

                    // Asset types (and Package type)
                    var assemblyContainsPackageType = assembly == typeof(Package).Assembly;
                    if (assemblyScanTypes.Types.TryGetValue(typeof(Asset), out types) || assemblyContainsPackageType)
                    {
                        if (assemblyContainsPackageType)
                        {
                            var extraTypes = new[] { typeof(Package) };
                            types = types?.Concat(extraTypes).ToList() ?? extraTypes.ToList();
                        }
                        foreach (var assetType in types)
                        {
                            // Store in a list all asset types loaded
                            if (assetType.IsPublic && !assetType.IsAbstract)
                            {
                                AssetTypes.Add(assetType);
                            }

                            // Asset FileExtensions
                            var assetDescriptionAttribute = assetType.GetCustomAttribute <AssetDescriptionAttribute>();
                            if (assetDescriptionAttribute != null)
                            {
                                if (assetDescriptionAttribute.FileExtensions != null)
                                {
                                    var extensions = FileUtility.GetFileExtensions(assetDescriptionAttribute.FileExtensions);
                                    RegisteredDefaultAssetExtension[assetType] = extensions.FirstOrDefault();
                                    foreach (var extension in extensions)
                                    {
                                        if (!RegisteredAssetFileExtensions.ContainsKey(extension))
                                        {
                                            RegisteredAssetFileExtensions.Add(extension, assetType);
                                        }
                                    }
                                }

                                if (assetDescriptionAttribute.AlwaysMarkAsRoot)
                                {
                                    lock (AlwaysMarkAsRootAssetTypes)
                                    {
                                        AlwaysMarkAsRootAssetTypes.Add(assetType);
                                    }
                                }
                            }

                            // Content type associated to assets
                            var assetContentType = assetType.GetCustomAttribute <AssetContentTypeAttribute>();
                            if (assetContentType != null)
                            {
                                List <Type> assetTypes;
                                if (!ContentToAssetTypes.TryGetValue(assetContentType.ContentType, out assetTypes))
                                {
                                    assetTypes = new List <Type>();
                                    ContentToAssetTypes[assetContentType.ContentType] = assetTypes;
                                }
                                assetTypes.Add(assetType);
                                AssetToContentTypes.Add(assetType, assetContentType.ContentType);
                            }

                            // Asset format version (process name by name)
                            var assetFormatVersions = assetType.GetCustomAttributes <AssetFormatVersionAttribute>();
                            foreach (var assetFormatVersion in assetFormatVersions)
                            {
                                var formatVersion = assetFormatVersion.Version;
                                var minVersion    = assetFormatVersion.MinUpgradableVersion;
                                SortedList <string, PackageVersion> formatVersions;
                                if (!RegisteredFormatVersions.TryGetValue(assetType, out formatVersions))
                                {
                                    RegisteredFormatVersions.Add(assetType, formatVersions = new SortedList <string, PackageVersion>());
                                }
                                formatVersions.Add(assetFormatVersion.Name, formatVersion);

                                // Asset upgraders (only those matching current name)
                                var assetUpgraders = assetType.GetCustomAttributes <AssetUpgraderAttribute>().Where(x => x.Name == assetFormatVersion.Name);
                                AssetUpgraderCollection upgraderCollection = null;
                                foreach (var upgrader in assetUpgraders)
                                {
                                    if (upgraderCollection == null)
                                    {
                                        upgraderCollection = new AssetUpgraderCollection(assetType, formatVersion);
                                    }

                                    upgraderCollection.RegisterUpgrader(upgrader.AssetUpgraderType, upgrader.StartVersion, upgrader.TargetVersion);
                                }
                                if (upgraderCollection != null)
                                {
                                    upgraderCollection.Validate(minVersion);
                                    RegisteredAssetUpgraders.Add(new KeyValuePair <Type, string>(assetType, assetFormatVersion.Name), upgraderCollection);
                                }
                            }

                            // Part reference types for asset composites
                            if (typeof(AssetComposite).IsAssignableFrom(assetType))
                            {
                                var attributes = assetType.GetCustomAttributes(typeof(AssetPartReferenceAttribute), true).Cast <AssetPartReferenceAttribute>().ToList();
                                foreach (var attribute in attributes)
                                {
                                    HashSet <AssetPartReferenceAttribute> relatedPartTypes;
                                    if (!RegisteredAssetCompositePartTypes.TryGetValue(attribute.ReferenceableType, out relatedPartTypes))
                                    {
                                        relatedPartTypes = new HashSet <AssetPartReferenceAttribute>();
                                        RegisteredAssetCompositePartTypes.Add(attribute.ReferenceableType, relatedPartTypes);
                                    }
                                    attributes.ForEach(x => relatedPartTypes.Add(x));
                                }
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Registers the asset assembly. This assembly should provide <see cref="Asset"/> objects, associated with
        /// <see cref="IAssetCompiler"/> and optionaly a <see cref="IAssetImporter"/>.
        /// </summary>
        /// <param name="assembly">The assembly.</param>
        /// <exception cref="System.ArgumentNullException">assembly</exception>
        /// <exception cref="AssetException">
        /// Invalid compiler type [{0}], must inherit from IAssetImporter.ToFormat(assetCompiler.TypeName)
        /// or
        /// Unable to instantiate compiler [{0}].ToFormat(assetCompiler.TypeName)
        /// or
        /// Invalid importer type [{0}], must inherit from IAssetImporter.ToFormat(assetImporter.ImpoterTypeName)
        /// or
        /// Unable to instantiate importer [{0}].ToFormat(assetImporter.ImpoterTypeName)
        /// </exception>
        public static void RegisterAssembly(Assembly assembly)
        {
            if (assembly == null)
            {
                throw new ArgumentNullException("assembly");
            }

            lock (RegisteredAssemblies)
            {
                if (RegisteredAssemblies.Contains(assembly))
                {
                    return;
                }
                RegisteredAssemblies.Add(assembly);
            }

            // Process Asset types.
            foreach (var type in assembly.GetTypes())
            {
                // Register serializer factories
                if (type.GetCustomAttribute <YamlSerializerFactoryAttribute>() != null)
                {
                    if (typeof(IYamlSerializableFactory).IsAssignableFrom(type))
                    {
                        try
                        {
                            var yamlFactory = (IYamlSerializableFactory)Activator.CreateInstance(type);
                            lock (RegisteredSerializerFactories)
                            {
                                RegisteredSerializerFactories.Add(yamlFactory);
                            }
                            // TODO: Handle IDataCustomVisitor on its own instead of relying on the coupling with IYamlSerializableFactory
                            var dataCustomVisitor = yamlFactory as IDataCustomVisitor;
                            if (dataCustomVisitor != null)
                            {
                                lock (RegisteredDataVisitNodes)
                                {
                                    RegisteredDataVisitNodes.Add(dataCustomVisitor);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Log.Error("Unable to instantiate serializer factory [{0}]", ex, type);
                        }
                    }
                }

                if (type.GetCustomAttribute <DiffNodeBuilderAttribute>() != null)
                {
                    if (typeof(IDataCustomVisitor).IsAssignableFrom(type))
                    {
                        try
                        {
                            var dataCustomVisitor = (IDataCustomVisitor)Activator.CreateInstance(type);
                            lock (RegisteredDataVisitNodeBuilders)
                            {
                                RegisteredDataVisitNodeBuilders.Add(dataCustomVisitor);
                            }
                        }
                        catch (Exception ex)
                        {
                            Log.Error("Unable to instantiate diff converter [{0}]", ex, type);
                        }
                    }
                }

                // Asset importer
                if (typeof(IAssetImporter).IsAssignableFrom(type) && type.GetConstructor(new Type[0]) != null)
                {
                    try
                    {
                        var importerInstance = Activator.CreateInstance(type) as IAssetImporter;

                        // Register the importer instance
                        RegisterImporter(importerInstance);
                    }
                    catch (Exception ex)
                    {
                        Log.Error("Unable to instantiate importer [{0}]", ex, type.Name);
                    }
                }

                if (typeof(PackageSessionAnalysisBase).IsAssignableFrom(type) && type.GetConstructor(new Type[0]) != null)
                {
                    RegisteredPackageSessionAnalysisTypes.Add(type);
                }

                {
                    var packageUpgraderAttribute = type.GetCustomAttribute <PackageUpgraderAttribute>();
                    if (packageUpgraderAttribute != null)
                    {
                        try
                        {
                            var packageUpgrader = (PackageUpgrader)Activator.CreateInstance(type);
                            packageUpgrader.Attribute = packageUpgraderAttribute;
                            RegisteredPackageUpgraders[packageUpgraderAttribute.PackageName] = packageUpgrader;
                        }
                        catch (Exception ex)
                        {
                            Log.Error("Unable to instantiate package upgrader [{0}]", ex, type.Name);
                        }
                    }
                }

                // Only process Asset types
                var assetType = type;
                if (!typeof(Asset).IsAssignableFrom(assetType) || !assetType.IsClass)
                {
                    continue;
                }

                // Store in a list all asset types loaded
                if (assetType.IsPublic && !assetType.IsAbstract)
                {
                    AssetTypes.Add(assetType);
                }

                var isSourceCodeAsset = typeof(SourceCodeAsset).IsAssignableFrom(assetType);

                // Asset FileExtensions
                var assetDescriptionAttribute = assetType.GetCustomAttribute <AssetDescriptionAttribute>();
                if (assetDescriptionAttribute != null)
                {
                    if (assetDescriptionAttribute.FileExtensions != null)
                    {
                        var extensions = FileUtility.GetFileExtensions(assetDescriptionAttribute.FileExtensions);
                        RegisteredDefaultAssetExtension[assetType] = extensions.FirstOrDefault();
                        foreach (var extension in extensions)
                        {
                            RegisteredAssetFileExtensions.Add(extension);

                            // If the asset is a pure sourcecode asset, then register the serializer
                            if (isSourceCodeAsset)
                            {
                                SourceCodeAssetSerializer.RegisterExtension(assetType, extension);
                            }
                        }
                    }
                    if (!assetDescriptionAttribute.AllowUserCreation)
                    {
                        RegisteredInternalAssetTypes.Add(assetType);
                    }
                }

                // Asset format version
                var assetFormatVersion = assetType.GetCustomAttribute <AssetFormatVersionAttribute>();
                int formatVersion      = assetFormatVersion != null ? assetFormatVersion.Version : 0;
                int minVersion         = assetFormatVersion != null ? assetFormatVersion.MinUpgradableVersion : 0;
                RegisteredFormatVersions.Add(assetType, Tuple.Create(minVersion, formatVersion));

                // Asset upgraders
                var assetUpgraders = assetType.GetCustomAttributes <AssetUpgraderAttribute>();
                AssetUpgraderCollection upgraderCollection = null;
                foreach (var upgrader in assetUpgraders)
                {
                    if (upgraderCollection == null)
                    {
                        upgraderCollection = new AssetUpgraderCollection(assetType, formatVersion);
                    }

                    upgraderCollection.RegisterUpgrader(upgrader.AssetUpgraderType, upgrader.StartMinVersion, upgrader.StartMaxVersion, upgrader.TargetVersion);
                }
                if (upgraderCollection != null)
                {
                    upgraderCollection.Validate(minVersion);
                    RegisteredAssetUpgraders.Add(assetType, upgraderCollection);
                }

                // Asset factory
                var assetFactory = assetType.GetCustomAttribute <ObjectFactoryAttribute>();
                if (assetFactory != null)
                {
                    try
                    {
                        ObjectFactory.RegisterFactory(assetType);
                    }
                    catch (Exception ex)
                    {
                        Log.Error("Unable to instantiate factory [{0}] for asset [{1}]", ex, assetFactory.FactoryTypeName, assetType);
                    }
                }
                else
                {
                    var assetConstructor = assetType.GetConstructor(Type.EmptyTypes);
                    if (assetConstructor != null)
                    {
                        // Register the asset even if it has no factory (default using empty constructor)
                        ObjectFactory.RegisterFactory(assetType, null);
                    }
                }

                // Asset description
                var thumbnailCompilerAttribute = assetType.GetCustomAttribute <ThumbnailCompilerAttribute>();
                if (thumbnailCompilerAttribute != null)
                {
                    RegisterDynamicThumbnail(assetType, thumbnailCompilerAttribute.DynamicThumbnails);
                }
            }
        }