--- /dev/null
+/*
+* Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the License);
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an AS IS BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+using System;
+using System.IO;
+using System.Reflection;
+using System.Runtime.Loader;
+
+using SystemIO = System.IO;
+
+namespace Tizen.NUI
+{
+ internal class NUIGadgetAssemblyLoadContext : AssemblyLoadContext
+ {
+ public NUIGadgetAssemblyLoadContext() : base(isCollectible: true)
+ {
+ }
+
+ protected override Assembly Load(AssemblyName name)
+ {
+ return null;
+ }
+ }
+
+ internal class NUIGadgetAssembly
+ {
+ private static readonly object _assemblyLock = new object();
+ private readonly string _assemblyPath;
+ private WeakReference _assemblyRef;
+ private Assembly _assembly = null;
+
+ public NUIGadgetAssembly(string assemblyPath) { _assemblyPath = assemblyPath; }
+
+ public void Load()
+ {
+ lock (_assemblyLock)
+ {
+ if (_assembly != null)
+ {
+ return;
+ }
+
+ Log.Warn("Load(): " + _assemblyPath + " ++");
+ NUIGadgetAssemblyLoadContext context = new NUIGadgetAssemblyLoadContext();
+ _assemblyRef = new WeakReference(context);
+ string directoryPath = SystemIO.Path.GetDirectoryName(_assemblyPath);
+ string fileName = SystemIO.Path.GetFileNameWithoutExtension(_assemblyPath);
+ string nativeImagePath = directoryPath + "/.native_image/" + fileName + ".ni.dll";
+ Log.Debug("NativeImagePath=" + nativeImagePath + ", AssemblyPath=" + _assemblyPath);
+ _assembly = context.LoadFromNativeImagePath(nativeImagePath, _assemblyPath);
+ Log.Warn("Load(): " + _assemblyPath + " --");
+ }
+ }
+
+ public bool IsLoaded { get { return _assembly != null; } }
+
+ public NUIGadget CreateInstance(string className)
+ {
+ lock (_assemblyLock)
+ {
+ return (NUIGadget)_assembly?.CreateInstance(className);
+ }
+ }
+
+ public void Unload()
+ {
+ lock (_assemblyLock)
+ {
+ if (_assembly == null)
+ {
+ return;
+ }
+
+ Log.Warn("Unload(): " + _assemblyPath + " ++");
+ if (_assemblyRef.IsAlive)
+ {
+ (_assemblyRef.Target as NUIGadgetAssemblyLoadContext).Unload();
+ }
+
+ _assembly = null;
+ Log.Warn("Unload(): " + _assemblyPath + " --");
+ }
+ }
+ }
+}
\ No newline at end of file
/// <since_tizen> 10 </since_tizen>
public static void Load(string resourceType)
{
+ Load(resourceType, true);
+ }
+
+ /// <summary>
+ /// Loads an assembly of the NUIGadget.
+ /// </summary>
+ /// <param name="resourceType">The resource type of the NUIGadget package.</param>
+ /// <param name="useDefaultContext">The flag if ture, use a default load context. Otherwise, use a new load context.</param>
+ /// <exception cref="ArgumentException">Thrown when failed because of a invalid argument.</exception>
+ /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
+ /// <since_tizen> 10 </since_tizen>
+ public static void Load(string resourceType, bool useDefaultContext)
+ {
if (string.IsNullOrEmpty(resourceType))
{
throw new ArgumentException("Invalid argument");
}
NUIGadgetInfo info = Find(resourceType);
- Load(info);
+ Load(info, useDefaultContext);
+ }
+
+ /// <summary>
+ /// Unloads the loaded assembly of the NUIGadget.
+ /// </summary>
+ /// <param name="resourceType">The resource type of the NUIGadget package.</param>
+ /// <exception cref="ArgumentException">Thrown when failed because of a invalid argument.</exception>
+ /// <since_tizen> 10 </since_tizen>
+ public static void Unload(string resourceType)
+ {
+ if (string.IsNullOrEmpty(resourceType))
+ {
+ throw new ArgumentException("Invalid argument");
+ }
+
+ NUIGadgetInfo info = Find(resourceType);
+ Unload(info);
+ }
+
+ private static void Unload(NUIGadgetInfo info)
+ {
+ if (info == null)
+ {
+ throw new ArgumentException("Invalid argument");
+ }
+
+ lock (info)
+ {
+ if (info.NUIGadgetAssembly != null && info.NUIGadgetAssembly.IsLoaded)
+ {
+ info.NUIGadgetAssembly.Unload();
+ info.NUIGadgetAssembly = null;
+ }
+ }
}
- private static void Load(NUIGadgetInfo info)
+ private static void Load(NUIGadgetInfo info, bool useDefaultContext)
{
if (info == null)
{
{
lock (info)
{
- if (info.Assembly == null)
+ if (useDefaultContext)
{
+ if (info.Assembly == null)
+ {
- Log.Warn("NUIGadgetAssembly.Load(): " + info.ResourcePath + info.ExecutableFile + " ++");
- info.Assembly = Assembly.Load(SystemIO.Path.GetFileNameWithoutExtension(info.ExecutableFile));
- Log.Warn("NUIGadgetAssembly.Load(): " + info.ResourcePath + info.ExecutableFile + " --");
+ Log.Warn("NUIGadget.Load(): " + info.ResourcePath + info.ExecutableFile + " ++");
+ info.Assembly = Assembly.Load(SystemIO.Path.GetFileNameWithoutExtension(info.ExecutableFile));
+ Log.Warn("NUIGadget.Load(): " + info.ResourcePath + info.ExecutableFile + " --");
+ }
+ }
+ else
+ {
+ if (info.NUIGadgetAssembly == null)
+ {
+ Log.Warn("NUIGadgetAssembly.Load(): " + info.ResourcePath + info.ExecutableFile + " ++");
+ info.NUIGadgetAssembly = new NUIGadgetAssembly(info.ResourcePath + info.ExecutableFile);
+ info.NUIGadgetAssembly.Load();
+ Log.Warn("NUIGadgetAssembly.Load(): " + info.ResourcePath + info.ExecutableFile + " --");
+ }
}
}
}
/// <since_tizen> 10 </since_tizen>
public static NUIGadget Add(string resourceType, string className)
{
+ return Add(resourceType, className, true);
+ }
+
+ /// <summary>
+ /// Adds a NUIGadget to the NUIGadgetManager.
+ /// </summary>
+ /// <param name="resourceType">The resource type of the NUIGadget package.</param>
+ /// <param name="className">The class name of the NUIGadget.</param>
+ /// <param name="useDefaultContext">The flag it true, use a default context. Otherwise, use a new load context.</param>
+ /// <returns>The NUIGadget object.</returns>
+ /// <exception cref="ArgumentException">Thrown when failed because of a invalid argument.</exception>
+ /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
+ /// <since_tizen> 10 </since_tizen>
+ public static NUIGadget Add(string resourceType, string className, bool useDefaultContext)
+ {
if (string.IsNullOrEmpty(resourceType) || string.IsNullOrEmpty(className))
{
throw new ArgumentException("Invalid argument");
}
NUIGadgetInfo info = Find(resourceType);
- Load(info);
+ Load(info, useDefaultContext);
- NUIGadget gadget = info.Assembly.CreateInstance(className, true) as NUIGadget;
+ NUIGadget gadget = useDefaultContext ? info.Assembly.CreateInstance(className, true) as NUIGadget : info.NUIGadgetAssembly.CreateInstance(className);
if (gadget == null)
{
throw new InvalidOperationException("Failed to create instance. className: " + className);