Files
FlaxEngine/Source/Engine/Scripting/ManagedCLR/MAssembly.h
2022-01-14 13:31:12 +01:00

243 lines
6.3 KiB
C++

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