mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-07 16:45:10 +00:00
优化Activator.CreateInstance, 已知类型优先使用new 代替反射,其次使用EmitHelper。耗时对比:直接new 1,EmitHelper 3, Activator 10。
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
using GameLogic;
|
using GameLogic;
|
||||||
using TEngine;
|
using TEngine;
|
||||||
@@ -8,35 +9,43 @@ using UnityEngine.UI;
|
|||||||
|
|
||||||
namespace GameLogic
|
namespace GameLogic
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UI管理模块。
|
||||||
|
/// </summary>
|
||||||
public sealed partial class UIModule : Singleton<UIModule>, IUpdate
|
public sealed partial class UIModule : Singleton<UIModule>, IUpdate
|
||||||
{
|
{
|
||||||
private static Transform _instanceRoot = null;
|
// 核心字段
|
||||||
|
private static Transform _instanceRoot = null; // UI根节点变换组件
|
||||||
private bool _enableErrorLog = true;
|
private bool _enableErrorLog = true; // 是否启用错误日志
|
||||||
|
private Camera _uiCamera = null; // UI专用摄像机
|
||||||
private Camera _uiCamera = null;
|
private readonly List<UIWindow> _uiStack = new List<UIWindow>(128); // 窗口堆栈
|
||||||
|
private ErrorLogger _errorLogger; // 错误日志记录器
|
||||||
private readonly List<UIWindow> _uiStack = new List<UIWindow>(100);
|
|
||||||
|
|
||||||
|
// 常量定义
|
||||||
public const int LAYER_DEEP = 2000;
|
public const int LAYER_DEEP = 2000;
|
||||||
public const int WINDOW_DEEP = 100;
|
public const int WINDOW_DEEP = 100;
|
||||||
public const int WINDOW_HIDE_LAYER = 2; // Ignore Raycast
|
public const int WINDOW_HIDE_LAYER = 2; // Ignore Raycast
|
||||||
public const int WINDOW_SHOW_LAYER = 5; // UI
|
public const int WINDOW_SHOW_LAYER = 5; // UI
|
||||||
|
|
||||||
|
// 资源加载接口
|
||||||
public static IUIResourceLoader Resource;
|
public static IUIResourceLoader Resource;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// UI根节点。
|
/// UI根节点访问属性
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Transform UIRoot => _instanceRoot;
|
public static Transform UIRoot => _instanceRoot;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// UI根节点。
|
/// UI摄像机访问属性
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Camera UICamera => _uiCamera;
|
public Camera UICamera => _uiCamera;
|
||||||
|
|
||||||
private ErrorLogger _errorLogger;
|
/// <summary>
|
||||||
|
/// 模块初始化(自动调用)。
|
||||||
|
/// 1. 查找场景中的UIRoot
|
||||||
|
/// 2. 初始化资源加载器
|
||||||
|
/// 3. 配置错误日志系统
|
||||||
|
/// </summary>
|
||||||
protected override void OnInit()
|
protected override void OnInit()
|
||||||
{
|
{
|
||||||
var uiRoot = GameObject.Find("UIRoot");
|
var uiRoot = GameObject.Find("UIRoot");
|
||||||
@@ -84,6 +93,12 @@ namespace GameLogic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 模块释放(自动调用)。
|
||||||
|
/// 1. 清理错误日志系统
|
||||||
|
/// 2. 关闭所有窗口
|
||||||
|
/// 3. 销毁UI根节点
|
||||||
|
/// </summary>
|
||||||
protected override void OnRelease()
|
protected override void OnRelease()
|
||||||
{
|
{
|
||||||
if (_errorLogger != null)
|
if (_errorLogger != null)
|
||||||
@@ -103,7 +118,7 @@ namespace GameLogic
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置屏幕安全区域(异形屏支持)。
|
/// 设置屏幕安全区域(异形屏支持)。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="safeRect">安全区域</param>
|
/// <param name="safeRect">安全区域矩形(基于屏幕像素坐标)。</param>
|
||||||
public static void ApplyScreenSafeRect(Rect safeRect)
|
public static void ApplyScreenSafeRect(Rect safeRect)
|
||||||
{
|
{
|
||||||
CanvasScaler scaler = UIRoot.GetComponentInParent<CanvasScaler>();
|
CanvasScaler scaler = UIRoot.GetComponentInParent<CanvasScaler>();
|
||||||
@@ -232,9 +247,9 @@ namespace GameLogic
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userDatas">用户自定义数据。</param>
|
/// <param name="userDatas">用户自定义数据。</param>
|
||||||
/// <returns>打开窗口操作句柄。</returns>
|
/// <returns>打开窗口操作句柄。</returns>
|
||||||
public void ShowUIAsync<T>(params System.Object[] userDatas) where T : UIWindow
|
public void ShowUIAsync<T>(params System.Object[] userDatas) where T : UIWindow , new()
|
||||||
{
|
{
|
||||||
ShowUIImp(typeof(T), true, userDatas);
|
ShowUIImp<T>(true, userDatas);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -254,9 +269,9 @@ namespace GameLogic
|
|||||||
/// <typeparam name="T">窗口类。</typeparam>
|
/// <typeparam name="T">窗口类。</typeparam>
|
||||||
/// <param name="userDatas">用户自定义数据。</param>
|
/// <param name="userDatas">用户自定义数据。</param>
|
||||||
/// <returns>打开窗口操作句柄。</returns>
|
/// <returns>打开窗口操作句柄。</returns>
|
||||||
public void ShowUI<T>(params System.Object[] userDatas) where T : UIWindow
|
public void ShowUI<T>(params System.Object[] userDatas) where T : UIWindow , new()
|
||||||
{
|
{
|
||||||
ShowUIImp(typeof(T), false, userDatas);
|
ShowUIImp<T>(false, userDatas);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -264,9 +279,9 @@ namespace GameLogic
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userDatas">用户自定义数据。</param>
|
/// <param name="userDatas">用户自定义数据。</param>
|
||||||
/// <returns>打开窗口操作句柄。</returns>
|
/// <returns>打开窗口操作句柄。</returns>
|
||||||
public async UniTask<T> ShowUIAsyncAwait<T>(params System.Object[] userDatas) where T : UIWindow
|
public async UniTask<T> ShowUIAsyncAwait<T>(params System.Object[] userDatas) where T : UIWindow , new()
|
||||||
{
|
{
|
||||||
return await ShowUIAwaitImp(typeof(T), true, userDatas) as T;
|
return await ShowUIAwaitImp<T>(true, userDatas) as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -284,38 +299,54 @@ namespace GameLogic
|
|||||||
{
|
{
|
||||||
string windowName = type.FullName;
|
string windowName = type.FullName;
|
||||||
|
|
||||||
// 如果窗口已经存在
|
if (!TryGetWindow(windowName, out UIWindow window, userDatas))
|
||||||
if (IsContains(windowName))
|
|
||||||
{
|
{
|
||||||
UIWindow window = GetWindow(windowName);
|
window = CreateInstance(type);
|
||||||
Pop(window); //弹出窗口
|
|
||||||
Push(window); //重新压入
|
|
||||||
window.TryInvoke(OnWindowPrepare, userDatas);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UIWindow window = CreateInstance(type);
|
|
||||||
Push(window); //首次压入
|
Push(window); //首次压入
|
||||||
window.InternalLoad(window.AssetName, OnWindowPrepare, isAsync, userDatas).Forget();
|
window.InternalLoad(window.AssetName, OnWindowPrepare, isAsync, userDatas).Forget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async UniTask<UIWindow> ShowUIAwaitImp(Type type, bool isAsync, params System.Object[] userDatas)
|
private void ShowUIImp<T>(bool isAsync, params System.Object[] userDatas) where T : UIWindow , new()
|
||||||
{
|
{
|
||||||
|
Type type = typeof(T);
|
||||||
string windowName = type.FullName;
|
string windowName = type.FullName;
|
||||||
|
|
||||||
// 如果窗口已经存在
|
if (!TryGetWindow(windowName, out UIWindow window, userDatas))
|
||||||
|
{
|
||||||
|
window = CreateInstance<T>();
|
||||||
|
Push(window); //首次压入
|
||||||
|
window.InternalLoad(window.AssetName, OnWindowPrepare, isAsync, userDatas).Forget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryGetWindow(string windowName,out UIWindow window, params System.Object[] userDatas)
|
||||||
|
{
|
||||||
|
window = null;
|
||||||
if (IsContains(windowName))
|
if (IsContains(windowName))
|
||||||
{
|
{
|
||||||
UIWindow window = GetWindow(windowName);
|
window = GetWindow(windowName);
|
||||||
Pop(window); //弹出窗口
|
Pop(window); //弹出窗口
|
||||||
Push(window); //重新压入
|
Push(window); //重新压入
|
||||||
window.TryInvoke(OnWindowPrepare, userDatas);
|
window.TryInvoke(OnWindowPrepare, userDatas);
|
||||||
return window;
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async UniTask<T> ShowUIAwaitImp<T>(bool isAsync, params System.Object[] userDatas) where T : UIWindow , new()
|
||||||
|
{
|
||||||
|
Type type = typeof(T);
|
||||||
|
string windowName = type.FullName;
|
||||||
|
|
||||||
|
if (TryGetWindow(windowName, out UIWindow window, userDatas))
|
||||||
|
{
|
||||||
|
return window as T;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UIWindow window = CreateInstance(type);
|
window = CreateInstance<T>();
|
||||||
Push(window); //首次压入
|
Push(window); //首次压入
|
||||||
window.InternalLoad(window.AssetName, OnWindowPrepare, isAsync, userDatas).Forget();
|
window.InternalLoad(window.AssetName, OnWindowPrepare, isAsync, userDatas).Forget();
|
||||||
float time = 0f;
|
float time = 0f;
|
||||||
@@ -328,13 +359,14 @@ namespace GameLogic
|
|||||||
}
|
}
|
||||||
await UniTask.Yield();
|
await UniTask.Yield();
|
||||||
}
|
}
|
||||||
return window;
|
return window as T;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 关闭窗口
|
/// 关闭窗口。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <typeparam name="T">窗口类型</typeparam>
|
||||||
public void CloseUI<T>() where T : UIWindow
|
public void CloseUI<T>() where T : UIWindow
|
||||||
{
|
{
|
||||||
CloseUI(typeof(T));
|
CloseUI(typeof(T));
|
||||||
@@ -375,7 +407,7 @@ namespace GameLogic
|
|||||||
|
|
||||||
window.Visible = false;
|
window.Visible = false;
|
||||||
window.IsHide = true;
|
window.IsHide = true;
|
||||||
window.HideTimerId = ModuleSystem.GetModule<ITimerModule>().AddTimer((arg) =>
|
window.HideTimerId = GameModule.Timer.AddTimer((arg) =>
|
||||||
{
|
{
|
||||||
CloseUI(type);
|
CloseUI(type);
|
||||||
},window.HideTimeToClose);
|
},window.HideTimeToClose);
|
||||||
@@ -482,9 +514,31 @@ namespace GameLogic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private UIWindow CreateInstance<T>() where T : UIWindow , new()
|
||||||
|
{
|
||||||
|
Type type = typeof(T);
|
||||||
|
UIWindow window = new T();
|
||||||
|
WindowAttribute attribute = Attribute.GetCustomAttribute(type, typeof(WindowAttribute)) as WindowAttribute;
|
||||||
|
|
||||||
|
if (window == null)
|
||||||
|
throw new GameFrameworkException($"Window {type.FullName} create instance failed.");
|
||||||
|
|
||||||
|
if (attribute != null)
|
||||||
|
{
|
||||||
|
string assetName = string.IsNullOrEmpty(attribute.Location) ? type.Name : attribute.Location;
|
||||||
|
window.Init(type.FullName, attribute.WindowLayer, attribute.FullScreen, assetName, attribute.FromResources, attribute.HideTimeToClose);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window.Init(type.FullName, (int)UILayer.UI, fullScreen: window.FullScreen, assetName: type.Name, fromResources: false, hideTimeToClose: 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
private UIWindow CreateInstance(Type type)
|
private UIWindow CreateInstance(Type type)
|
||||||
{
|
{
|
||||||
UIWindow window = Activator.CreateInstance(type) as UIWindow;
|
UIWindow window = EmitHelper.CreateInstance(type) as UIWindow;
|
||||||
WindowAttribute attribute = Attribute.GetCustomAttribute(type, typeof(WindowAttribute)) as WindowAttribute;
|
WindowAttribute attribute = Attribute.GetCustomAttribute(type, typeof(WindowAttribute)) as WindowAttribute;
|
||||||
|
|
||||||
if (window == null)
|
if (window == null)
|
||||||
@@ -507,7 +561,7 @@ namespace GameLogic
|
|||||||
/// 异步获取窗口。
|
/// 异步获取窗口。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>打开窗口操作句柄。</returns>
|
/// <returns>打开窗口操作句柄。</returns>
|
||||||
public async UniTask<T> GetUIAsyncAwait<T>() where T : UIWindow
|
public async UniTask<T> GetUIAsyncAwait<T>(CancellationToken cancellationToken) where T : UIWindow
|
||||||
{
|
{
|
||||||
string windowName = typeof(T).FullName;
|
string windowName = typeof(T).FullName;
|
||||||
var window = GetWindow(windowName);
|
var window = GetWindow(windowName);
|
||||||
@@ -536,7 +590,7 @@ namespace GameLogic
|
|||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
await UniTask.Yield();
|
await UniTask.Yield(cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -612,7 +666,9 @@ namespace GameLogic
|
|||||||
{
|
{
|
||||||
// 如果已经存在
|
// 如果已经存在
|
||||||
if (IsContains(window.WindowName))
|
if (IsContains(window.WindowName))
|
||||||
throw new System.Exception($"Window {window.WindowName} is exist.");
|
{
|
||||||
|
throw new GameFrameworkException($"Window {window.WindowName} is exist.");
|
||||||
|
}
|
||||||
|
|
||||||
// 获取插入到所属层级的位置
|
// 获取插入到所属层级的位置
|
||||||
int insertIndex = -1;
|
int insertIndex = -1;
|
||||||
|
@@ -55,7 +55,7 @@ namespace GameLogic
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 窗口可见性
|
/// 窗口可见性。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Visible
|
public bool Visible
|
||||||
{
|
{
|
||||||
@@ -278,7 +278,7 @@ namespace GameLogic
|
|||||||
/// 组件被销毁调用。
|
/// 组件被销毁调用。
|
||||||
/// <remarks>请勿手动调用!</remarks>
|
/// <remarks>请勿手动调用!</remarks>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void OnDestroyWidget()
|
protected internal void OnDestroyWidget()
|
||||||
{
|
{
|
||||||
Parent?.SetUpdateDirty();
|
Parent?.SetUpdateDirty();
|
||||||
|
|
||||||
|
@@ -130,7 +130,7 @@ namespace GameLogic
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 窗口可见性
|
/// 窗口可见性。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Visible
|
public bool Visible
|
||||||
{
|
{
|
||||||
@@ -174,7 +174,7 @@ namespace GameLogic
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 窗口交互性
|
/// 窗口交互性。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool Interactable
|
private bool Interactable
|
||||||
{
|
{
|
||||||
|
@@ -14,8 +14,11 @@ namespace GameLogic
|
|||||||
System = 4,
|
System = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UI窗口属性。
|
||||||
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Class)]
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
public class WindowAttribute : Attribute
|
public class WindowAttribute : Attribute // 用于标记UI窗口,最好完整支持是做成配置表,可以支持货币栏位配置,UI跳转配置等等~
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 窗口层级
|
/// 窗口层级
|
||||||
|
@@ -77,7 +77,7 @@ namespace TEngine
|
|||||||
}
|
}
|
||||||
|
|
||||||
_addMemoryCount++;
|
_addMemoryCount++;
|
||||||
return (IMemory)Activator.CreateInstance(_memoryType);
|
return (IMemory)EmitHelper.CreateInstance(_memoryType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Release(IMemory memory)
|
public void Release(IMemory memory)
|
||||||
@@ -121,7 +121,7 @@ namespace TEngine
|
|||||||
_addMemoryCount += count;
|
_addMemoryCount += count;
|
||||||
while (count-- > 0)
|
while (count-- > 0)
|
||||||
{
|
{
|
||||||
_memories.Enqueue((IMemory)Activator.CreateInstance(_memoryType));
|
_memories.Enqueue((IMemory)EmitHelper.CreateInstance(_memoryType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -106,7 +106,7 @@ namespace TEngine
|
|||||||
/// <returns>要创建的游戏框架模块。</returns>
|
/// <returns>要创建的游戏框架模块。</returns>
|
||||||
private static Module CreateModule(Type moduleType)
|
private static Module CreateModule(Type moduleType)
|
||||||
{
|
{
|
||||||
Module module = (Module)Activator.CreateInstance(moduleType);
|
Module module = (Module)EmitHelper.CreateInstance(moduleType);
|
||||||
if (module == null)
|
if (module == null)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException(Utility.Text.Format("Can not create module '{0}'.", moduleType.FullName));
|
throw new GameFrameworkException(Utility.Text.Format("Can not create module '{0}'.", moduleType.FullName));
|
||||||
|
193
UnityProject/Assets/TEngine/Runtime/Core/Utility/EmitHelper.cs
Normal file
193
UnityProject/Assets/TEngine/Runtime/Core/Utility/EmitHelper.cs
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Reflection.Emit;
|
||||||
|
|
||||||
|
namespace TEngine
|
||||||
|
{
|
||||||
|
public static class EmitHelper
|
||||||
|
{
|
||||||
|
private static readonly Dictionary<Type, Delegate> _defaultCache = new Dictionary<Type, Delegate>();
|
||||||
|
|
||||||
|
private static readonly Dictionary<CacheKey, Delegate> _argCache = new Dictionary<CacheKey, Delegate>();
|
||||||
|
|
||||||
|
public static T CreateInstance<T>() where T : new()
|
||||||
|
{
|
||||||
|
var type = typeof(T);
|
||||||
|
|
||||||
|
if (!_defaultCache.TryGetValue(type, out var factory))
|
||||||
|
{
|
||||||
|
if (!_defaultCache.TryGetValue(type, out factory))
|
||||||
|
{
|
||||||
|
factory = CreateFactory<T>();
|
||||||
|
_defaultCache.TryAdd(type, factory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((Func<T>)factory)();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object CreateInstance(Type type)
|
||||||
|
{
|
||||||
|
if (!_defaultCache.TryGetValue(type, out var factory))
|
||||||
|
{
|
||||||
|
lock (_defaultCache)
|
||||||
|
{
|
||||||
|
if (!_defaultCache.TryGetValue(type, out factory))
|
||||||
|
{
|
||||||
|
var constructor = type.GetConstructor(
|
||||||
|
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
|
||||||
|
null, Type.EmptyTypes, null);
|
||||||
|
|
||||||
|
if (constructor == null)
|
||||||
|
{
|
||||||
|
throw new MissingMethodException($"No parameterless constructor defined for type '{type.FullName}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建动态方法(关键优化点)
|
||||||
|
var dynamicMethod = new DynamicMethod(
|
||||||
|
name: $"CreateInstance_{type.FullName}",
|
||||||
|
returnType: typeof(object),
|
||||||
|
parameterTypes: Type.EmptyTypes,
|
||||||
|
owner: typeof(object),
|
||||||
|
skipVisibility: true);
|
||||||
|
|
||||||
|
// 生成IL指令(核心逻辑)
|
||||||
|
var il = dynamicMethod.GetILGenerator();
|
||||||
|
|
||||||
|
// 处理值类型和引用类型的差异
|
||||||
|
if (type.IsValueType)
|
||||||
|
{
|
||||||
|
il.DeclareLocal(type);
|
||||||
|
il.Emit(OpCodes.Ldloca_S, 0);
|
||||||
|
il.Emit(OpCodes.Initobj, type);
|
||||||
|
il.Emit(OpCodes.Ldloc_0);
|
||||||
|
il.Emit(OpCodes.Box, type); // 值类型需要装箱
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
il.Emit(OpCodes.Newobj, constructor);
|
||||||
|
}
|
||||||
|
|
||||||
|
il.Emit(OpCodes.Ret);
|
||||||
|
|
||||||
|
factory = dynamicMethod.CreateDelegate(typeof(Func<object>));
|
||||||
|
_defaultCache.TryAdd(type, factory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((Func<object>)factory)();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Func<T> CreateFactory<T>() where T : new()
|
||||||
|
{
|
||||||
|
var constructor = typeof(T).GetConstructor(
|
||||||
|
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
|
||||||
|
null, Type.EmptyTypes, null);
|
||||||
|
|
||||||
|
var dynamicMethod = new DynamicMethod(
|
||||||
|
name: $"CreateInstance_{typeof(T).FullName}",
|
||||||
|
returnType: typeof(T),
|
||||||
|
parameterTypes: Type.EmptyTypes,
|
||||||
|
owner: typeof(object), // 关键优化:使用object类型模块
|
||||||
|
skipVisibility: true);
|
||||||
|
|
||||||
|
var il = dynamicMethod.GetILGenerator();
|
||||||
|
il.Emit(OpCodes.Newobj, constructor);
|
||||||
|
il.Emit(OpCodes.Ret);
|
||||||
|
|
||||||
|
return (Func<T>)dynamicMethod.CreateDelegate(typeof(Func<T>));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static object CreateInstance(Type type, params object[] args)
|
||||||
|
{
|
||||||
|
if (type == null) throw new ArgumentNullException(nameof(type));
|
||||||
|
args ??= Array.Empty<object>();
|
||||||
|
|
||||||
|
// 预转换参数类型数组
|
||||||
|
var argTypes = Array.ConvertAll(args, a => a?.GetType() ?? typeof(object));
|
||||||
|
var cacheKey = new CacheKey(type, argTypes);
|
||||||
|
|
||||||
|
if (!_argCache.TryGetValue(cacheKey, out var factory))
|
||||||
|
{
|
||||||
|
if (!_argCache.TryGetValue(cacheKey, out factory))
|
||||||
|
{
|
||||||
|
// 预热动态方法生成
|
||||||
|
factory = CreateDynamicFactory(type, argTypes);
|
||||||
|
_argCache.TryAdd(cacheKey, factory);
|
||||||
|
|
||||||
|
// 预热编译器
|
||||||
|
((Func<object[], object>)factory)(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((Func<object[], object>)factory)(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Func<object[], object> CreateDynamicFactory(Type type, Type[] argTypes)
|
||||||
|
{
|
||||||
|
// 精确匹配构造函数
|
||||||
|
var constructor = type.GetConstructor(
|
||||||
|
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
|
||||||
|
null, argTypes, null) ?? throw new MissingMethodException(type.Name);
|
||||||
|
|
||||||
|
// 创建动态方法
|
||||||
|
var dynamicMethod = new DynamicMethod(
|
||||||
|
name: $"CreateInstance_{type.Name}",
|
||||||
|
returnType: typeof(object),
|
||||||
|
parameterTypes: new[] { typeof(object[]) },
|
||||||
|
owner: typeof(object),
|
||||||
|
skipVisibility: true);
|
||||||
|
|
||||||
|
var il = dynamicMethod.GetILGenerator();
|
||||||
|
|
||||||
|
for (int i = 0; i < argTypes.Length; i++)
|
||||||
|
{
|
||||||
|
// 高效参数加载序列(网页9 IL优化)
|
||||||
|
il.Emit(OpCodes.Ldarg_0);
|
||||||
|
il.Emit(OpCodes.Ldc_I4, i);
|
||||||
|
il.Emit(OpCodes.Ldelem_Ref);
|
||||||
|
|
||||||
|
// 类型转换合并优化
|
||||||
|
if (argTypes[i].IsValueType)
|
||||||
|
{
|
||||||
|
il.Emit(OpCodes.Unbox_Any, argTypes[i]);
|
||||||
|
}
|
||||||
|
else if (argTypes[i] != typeof(object))
|
||||||
|
{
|
||||||
|
il.Emit(OpCodes.Castclass, argTypes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
il.Emit(OpCodes.Newobj, constructor);
|
||||||
|
|
||||||
|
// 统一装箱处理
|
||||||
|
if (type.IsValueType)
|
||||||
|
{
|
||||||
|
il.Emit(OpCodes.Box, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
il.Emit(OpCodes.Ret);
|
||||||
|
|
||||||
|
return (Func<object[], object>)dynamicMethod.CreateDelegate(typeof(Func<object[], object>));
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly struct CacheKey
|
||||||
|
{
|
||||||
|
public readonly Type Type;
|
||||||
|
|
||||||
|
public readonly Type[] ArgTypes;
|
||||||
|
|
||||||
|
public CacheKey(Type type, Type[] argTypes)
|
||||||
|
{
|
||||||
|
Type = type;
|
||||||
|
ArgTypes = argTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode() => Type.GetHashCode() ^ ArgTypes.Aggregate(0, (h, t) => h ^ t.GetHashCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d629990b98cb407dafee703ef18dd2c5
|
||||||
|
timeCreated: 1742174169
|
@@ -1271,7 +1271,7 @@ namespace TEngine
|
|||||||
|
|
||||||
Type objectPoolType = typeof(ObjectPool<>).MakeGenericType(objectType);
|
Type objectPoolType = typeof(ObjectPool<>).MakeGenericType(objectType);
|
||||||
ObjectPoolBase objectPool =
|
ObjectPoolBase objectPool =
|
||||||
(ObjectPoolBase)Activator.CreateInstance(objectPoolType, name, allowMultiSpawn, autoReleaseInterval, capacity, expireTime, priority);
|
(ObjectPoolBase)EmitHelper.CreateInstance(objectPoolType, name, allowMultiSpawn, autoReleaseInterval, capacity, expireTime, priority);
|
||||||
_objectPools.Add(typeNamePair, objectPool);
|
_objectPools.Add(typeNamePair, objectPool);
|
||||||
return objectPool;
|
return objectPool;
|
||||||
}
|
}
|
||||||
|
@@ -75,7 +75,7 @@ namespace TEngine
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
procedures[i] = (ProcedureBase)Activator.CreateInstance(procedureType);
|
procedures[i] = (ProcedureBase)EmitHelper.CreateInstance(procedureType);
|
||||||
if (procedures[i] == null)
|
if (procedures[i] == null)
|
||||||
{
|
{
|
||||||
Log.Error("Can not create procedure instance '{0}'.", availableProcedureTypeNames[i]);
|
Log.Error("Can not create procedure instance '{0}'.", availableProcedureTypeNames[i]);
|
||||||
|
@@ -225,7 +225,7 @@ namespace TEngine
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utility.Text.ITextHelper textHelper = (Utility.Text.ITextHelper)Activator.CreateInstance(textHelperType);
|
Utility.Text.ITextHelper textHelper = (Utility.Text.ITextHelper)EmitHelper.CreateInstance(textHelperType);
|
||||||
if (textHelper == null)
|
if (textHelper == null)
|
||||||
{
|
{
|
||||||
Log.Error("Can not create text helper instance '{0}'.", textHelperTypeName);
|
Log.Error("Can not create text helper instance '{0}'.", textHelperTypeName);
|
||||||
@@ -250,7 +250,7 @@ namespace TEngine
|
|||||||
}
|
}
|
||||||
|
|
||||||
GameFrameworkLog.ILogHelper
|
GameFrameworkLog.ILogHelper
|
||||||
logHelper = (GameFrameworkLog.ILogHelper)Activator.CreateInstance(logHelperType);
|
logHelper = (GameFrameworkLog.ILogHelper)EmitHelper.CreateInstance(logHelperType);
|
||||||
if (logHelper == null)
|
if (logHelper == null)
|
||||||
{
|
{
|
||||||
throw new GameFrameworkException(Utility.Text.Format("Can not create log helper instance '{0}'.",
|
throw new GameFrameworkException(Utility.Text.Format("Can not create log helper instance '{0}'.",
|
||||||
@@ -274,7 +274,7 @@ namespace TEngine
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utility.Json.IJsonHelper jsonHelper = (Utility.Json.IJsonHelper)Activator.CreateInstance(jsonHelperType);
|
Utility.Json.IJsonHelper jsonHelper = (Utility.Json.IJsonHelper)EmitHelper.CreateInstance(jsonHelperType);
|
||||||
if (jsonHelper == null)
|
if (jsonHelper == null)
|
||||||
{
|
{
|
||||||
Log.Error("Can not create JSON helper instance '{0}'.", jsonHelperTypeName);
|
Log.Error("Can not create JSON helper instance '{0}'.", jsonHelperTypeName);
|
||||||
|
Reference in New Issue
Block a user