// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. #pragma once #include "MTypes.h" #include "MAssemblyOptions.h" #include "Engine/Core/Delegate.h" #include "Engine/Core/Types/String.h" #include "Engine/Core/Collections/Array.h" #include "Engine/Core/Collections/Dictionary.h" #include "Engine/Platform/CriticalSection.h" /// /// Represents a managed assembly, which is a reusable, versionable, and self-describing building block of a common language runtime application. /// class FLAXENGINE_API MAssembly { friend MDomain; public: typedef Dictionary ClassesDictionary; private: #if USE_MONO MonoAssembly* _monoAssembly = nullptr; MonoImage* _monoImage = nullptr; #endif MDomain* _domain; int32 _isLoaded : 1; int32 _isLoading : 1; int32 _isDependency : 1; int32 _isFileLocked : 1; mutable int32 _hasCachedClasses : 1; mutable ClassesDictionary _classes; CriticalSection _locker; int32 _reloadCount; MString _name; String _assemblyPath; Array _debugData; const MAssemblyOptions _options; public: /// /// Initializes a new instance of the class. /// /// The assembly domain. /// The assembly name. /// The assembly options. MAssembly(MDomain* domain, const StringAnsiView& name, const MAssemblyOptions& options); /// /// Finalizes an instance of the class. /// ~MAssembly(); public: /// /// Managed assembly actions delegate type. /// typedef Delegate AssemblyDelegate; /// /// Action fired when assembly starts loading. /// AssemblyDelegate Loading; /// /// Action fired when assembly gets loaded. /// AssemblyDelegate Loaded; /// /// Action fired when assembly loading fails. /// AssemblyDelegate LoadFailed; /// /// Action fired when assembly start unloading. /// AssemblyDelegate Unloading; /// /// Action fired when assembly gets unloaded. /// AssemblyDelegate Unloaded; public: /// /// Returns true if assembly is during loading state. /// FORCE_INLINE bool IsLoading() const { return _isLoading != 0; } /// /// Returns true if assembly has been loaded. /// FORCE_INLINE bool IsLoaded() const { return _isLoaded != 0; } /// /// Gets the assembly name. /// FORCE_INLINE const MString& GetName() const { return _name; } /// /// Gets the assembly name as string. /// String ToString() const; /// /// Gets the assembly path. /// /// /// If assembly was made from scratch (empty), path will return null. /// FORCE_INLINE const String& GetAssemblyPath() const { return _assemblyPath; } /// /// Gets the parent domain. /// FORCE_INLINE MDomain* GetDomain() const { return _domain; } #if USE_MONO /// /// Gets the Mono assembly. /// FORCE_INLINE MonoAssembly* GetMonoAssembly() const { return _monoAssembly; } /// /// Gets the Mono image. /// FORCE_INLINE MonoImage* GetMonoImage() const { return _monoImage; } #endif /// /// Gets the options that assembly was created with. /// FORCE_INLINE const MAssemblyOptions& GetOptions() const { return _options; } public: /// /// Loads assembly for domain. /// /// The assembly path. /// True if cannot load, otherwise false bool Load(const String& assemblyPath); #if USE_MONO /// /// Loads assembly for domain. /// /// The assembly image. /// True if cannot load, otherwise false. bool Load(MonoImage* monoImage); #endif /// /// Cleanup data. Caller must ensure not to use any types from this assembly after it has been unloaded. /// /// If true assembly is during reloading and should force release the runtime data. void Unload(bool isReloading = false); public: /// /// Attempts to find a managed class with the specified namespace and name in this assembly. Returns null if one cannot be found. /// /// The type name. /// The class object or null if failed to find it. MClass* GetClass(const StringAnsiView& typeName) const; #if USE_MONO /// /// Converts an internal mono representation of a class into engine class. /// /// The Mono class. /// The class object. MClass* GetClass(MonoClass* monoClass) const; /// /// Gets the native of the assembly (for the current domain). Can be used to pass to the scripting backend as a parameter. /// /// The native assembly object. MonoReflectionAssembly* GetNative() const; #endif /// /// Gets the classes lookup cache. Performs full initialization if not cached. The result cache contains all classes from the assembly. /// /// The cache. const ClassesDictionary& GetClasses() const; private: /// /// Loads the assembly for domain. /// /// True if failed, otherwise false. bool LoadDefault(const String& assemblyPath); /// /// Loads the assembly for domain from non-blocking image. /// /// True if failed, otherwise false. bool LoadWithImage(const String& assemblyPath); void OnLoading(); void OnLoaded(const struct DateTime& startTime); void OnLoadFailed(); };