using Serein.Library.Utils; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using static Serein.Library.Utils.EmitHelper; namespace Serein.Library { /// /// Emit创建的委托描述,用于WebApi、WebSocket、NodeFlow动态调用方法的场景。 /// 一般情况下你无须关注内部细节,只需要调用 Invoke() 方法即可。 /// public class DelegateDetails { /// /// 根据方法信息构建Emit委托 /// /// public DelegateDetails(MethodInfo methodInfo) { var emitMethodType = EmitHelper.CreateDynamicMethod(methodInfo, out var emitDelegate); _emitMethodInfo = emitMethodType; _emitDelegate = emitDelegate; } /*/// /// 更新委托方法 /// /// /// public void Upload(EmitMethodType EmitMethodType, Delegate EmitDelegate) { _emitMethodType = EmitMethodType; _emitDelegate = EmitDelegate; }*/ private Delegate _emitDelegate; private EmitMethodInfo _emitMethodInfo; ///// ///// 普通方法:Func<object,object[],object> ///// 异步方法:Func<object,object[],Task> ///// 异步有返回值方法:Func<object,object[],Task<object>> ///// //public Delegate EmitDelegate { get => _emitDelegate; } ///// ///// 表示Emit构造的委托类型 ///// //public EmitMethodType EmitMethodType { get => _emitMethodType; } public async Task AutoInvokeAsync(object[] args) { if (_emitMethodInfo.IsStatic) { return await InvokeAsync(null, args); } else { var obj = Activator.CreateInstance(_emitMethodInfo.DeclaringType); return await InvokeAsync(obj, args); } throw new Exception("Not static method"); } /// /// 使用的实例必须能够正确调用该委托,传入的参数也必须符合方法入参信息。 /// /// 拥有符合委托签名的方法信息的实例 /// 如果方法没有入参,也需要传入一个空数组 /// void方法自动返回null public async Task InvokeAsync(object instance, object[] args) { if (args is null) { args = Array.Empty(); } if(_emitMethodInfo.IsStatic) { instance = null; } object result = null; if (_emitDelegate is Func> hasResultTask) { result = await hasResultTask(instance, args); } else if (_emitDelegate is Func task) { await task.Invoke(instance, args); } else if (_emitDelegate is Func func) { result = func.Invoke(instance, args); } else { throw new NotImplementedException("创建了非预期委托(应该不会出现)"); } // return result; //try //{ //} //catch //{ // throw; //} } } }