/// <summary> /// 可能なら引数付きでコールバックを呼びます。 /// </summary> /// <param name="dummyArgumentsControl">仮引数コントロール</param> /// <param name="cagt">仮引数スタック</param> /// <param name="func">コールバック変数</param> /// <param name="arg">コールバック引数</param> protected void TryCallCallBack(DummyArgumentsControl dummyArgumentsControl, DummyArgumentsStack cagt, ICbValue func, object arg) { if (CanCallBack(func)) { CallCallBack(dummyArgumentsControl, cagt, func, arg); } }
/// <summary> /// 可能ならコールバックを呼びます。 /// </summary> /// <param name="cagt">仮引数スタック</param> /// <param name="func">コールバック変数</param> protected void TryCallCallBack(DummyArgumentsStack cagt, ICbValue func) { if (CanCallBack(func)) { CallCallBack(cagt, func); } }
/// <summary> /// コールバックを呼び出します。 /// </summary> /// <param name="variable">変数</param> /// <param name="dummyArgumentstack">仮引数スタック</param> /// <returns>コールバックの返し値</returns> protected ICbValue CallEvent(ICbValue variable, DummyArgumentsStack dummyArgumentstack) { ICbEvent cbEvent = variable as ICbEvent; cbEvent.InvokeCallback(dummyArgumentstack); return(cbEvent.Value); }
/// <summary> /// 引数付きでコールバックを呼びます。 /// </summary> /// <param name="dummyArgumentsControl">仮引数コントロール</param> /// <param name="cagt">仮引数スタック</param> /// <param name="func">コールバック変数</param> /// <param name="arg">コールバック引数</param> protected void CallCallBack(DummyArgumentsControl dummyArgumentsControl, DummyArgumentsStack cagt, ICbValue func, object arg) { if (arg is ICbValue cbValue) { dummyArgumentsControl.EnableCbValue(cagt, cbValue); // 仮引数に引数を登録 } else { dummyArgumentsControl.Enable(cagt, (dynamic)arg); // 仮引数に引数を登録 } CallEvent(func, cagt); dummyArgumentsControl.Invalidated(cagt); // 仮引数後処理 }
/// <summary> /// コールバックを呼んで返り値を得ます。 /// </summary> /// <typeparam name="R">返り値の型</typeparam> /// <param name="dummyArgumentsControl">仮引数コントロール</param> /// <param name="cagt">仮引数スタック</param> /// <param name="func">コールバック変数</param> /// <param name="def">コールバックの返り値を得られなかったときの返り値</param> /// <returns>コールバックの返り値</returns> protected R GetCallBackResult <R>(DummyArgumentsStack cagt, ICbValue func, R def) { if (!CanCallBack(func)) { return(def); } if (typeof(R) == typeof(ICbValue)) { ICbValue result = CallEvent(func, cagt); return((R)result); } else { R result = (R)CallEvent(func, cagt).Data; return(result); } }
/// <summary> /// オリジナル型の値に変換します。 /// </summary> /// <param name="value"></param> /// <param name="col"></param> /// <param name="dummyArgumentsControl"></param> /// <param name="dummyArgumentsStack"></param> /// <returns></returns> private object getBindObject( ICbValue value, MultiRootConnector col, DummyArgumentsControl dummyArgumentsControl, DummyArgumentsStack dummyArgumentsStack ) { if (value.IsList) { ICbList cbList = value.GetListValue; // リストは、オリジナルの型のインスタンスを用意する if (dummyArgumentsControl is null) { return(cbList.ConvertOriginalTypeList(col, dummyArgumentsStack)); } else { return(cbList.ConvertOriginalTypeList(dummyArgumentsControl, dummyArgumentsStack)); } } else if (dummyArgumentsControl != null && value is ICbEvent cbEvent) { // Func<> 及び Action<> は、オリジナルの型のインスタンスを用意する if (cbEvent.Callback is null) { return(null); } else { Debug.Assert(dummyArgumentsControl != null); return(cbEvent.GetCallbackOriginalType(dummyArgumentsControl, dummyArgumentsStack)); } } if (value.IsNull) { return(null); } return(value.Data); }
/// <summary> /// 引数をメソッドに合わせて調整しリストアップします。 /// </summary> /// <param name="col">スクリプトのルートノード</param> /// <param name="dummyArgumentsControl">仮引数管理オブジェクト</param> /// <param name="callArguments">引数リスト</param> /// <param name="dummyArgumentsStack">仮引数スタック</param> /// <param name="variableIds">スクリプト変数IDリスト</param> /// <param name="isClassInstanceMethod">インスタンスメソッドか?</param> /// <param name="methodArguments">メソッド呼び出し引数リスト</param> /// <returns>メソッド呼び出し引数リスト</returns> private List <object> SetArguments( MultiRootConnector col, DummyArgumentsControl dummyArgumentsControl, List <ICbValue> callArguments, DummyArgumentsStack dummyArgumentsStack, bool isClassInstanceMethod, List <object> methodArguments ) { int argumentIndex = 0; if (callArguments.Count > 0) { methodArguments ??= new List <object>(); } bool isTaskRequest = callArguments.Count(n => n.IsList || n is ICbEvent) > 2; // タスクで処理する条件 if (isTaskRequest) { // タスクを使った処理 List <Task <object> > tasks = new List <Task <object> >(); for (int i = 0; i < callArguments.Count; ++i) { var node = callArguments[argumentIndex++]; CheckArgument(node); if (i == 0 && isClassInstanceMethod) { // クラスメソッドの第一引数は、self(this)を受け取るのでメソッド呼び出しの引数にしない continue; } tasks.Add(Task.Run(() => { return(getBindObject(node, col, dummyArgumentsControl, dummyArgumentsStack)); })); } foreach (var task in tasks) { methodArguments.Add(task.Result); } } else { // 通常処理 for (int i = 0; i < callArguments.Count; ++i) { var node = callArguments[argumentIndex++]; CheckArgument(node); if (i == 0 && isClassInstanceMethod) { // クラスメソッドの第一引数は、self(this)を受け取るのでメソッド呼び出しの引数にしない continue; } methodArguments.Add(getBindObject(node, col, dummyArgumentsControl, dummyArgumentsStack)); } } return(methodArguments); }
/// <summary> /// メソッド呼び出しの実装です。 /// </summary> /// <param name="col">スクリプトのルートノード</param> /// <param name="dummyArgumentsControl">仮引数管理オブジェクト</param> /// <param name="callArguments">引数リスト</param> /// <param name="dummyArgumentsStack">仮引数スタック</param> /// <param name="returnValue">返り値</param> private void ImplCallMethod( MultiRootConnector col, Type classType, DummyArgumentsControl dummyArgumentsControl, List <ICbValue> callArguments, DummyArgumentsStack dummyArgumentsStack, ICbValue returnValue ) { try { bool isClassInstanceMethod = ArgumentTypeList != null && ArgumentTypeList[0].IsSelf && !IsConstructor; List <object> methodArguments = null; methodArguments = SetArguments( col, dummyArgumentsControl, callArguments, dummyArgumentsStack, isClassInstanceMethod, methodArguments ); object classInstance = null; if (isClassInstanceMethod) { // クラスメソッドの第一引数は、self(this)を受け取るのでクラスインスタンスとして扱う classInstance = getBindObject(callArguments[0], col, dummyArgumentsControl, dummyArgumentsStack); if (classInstance is null) { throw new Exception($"self(this) is invalid."); } // 返却方法が入っていないならセットしておく var cbVSValue = callArguments[0]; if (!cbVSValue.IsDelegate && !cbVSValue.IsLiteral && cbVSValue.ReturnAction is null) { if (cbVSValue.IsList) { ICbList cbList = cbVSValue.GetListValue; cbVSValue.ReturnAction = (value) => { cbList.CopyFrom(value); }; } else if (!(cbVSValue is ICbClass)) { cbVSValue.ReturnAction = (value) => { cbVSValue.Data = value; }; } } } object result = CallMethod( classInstance, col, classType, callArguments, isClassInstanceMethod, methodArguments); ProcReturnValue(col, returnValue, result); } catch (Exception ex) { col.ExceptionFunc(returnValue, ex); } }
/// <summary> /// 引数付きでコールバックを呼んで返り値を得ます。 /// </summary> /// <typeparam name="R">返り値の型</typeparam> /// <param name="dummyArgumentsControl">仮引数コントロール</param> /// <param name="cagt">仮引数スタック</param> /// <param name="func">コールバック変数</param> /// <param name="arg">コールバック引数</param> /// <param name="def">コールバックの返り値を得られなかったときの返り値</param> /// <returns>コールバックの返り値</returns> protected R GetCallBackResult <R>(DummyArgumentsControl dummyArgumentsControl, DummyArgumentsStack cagt, ICbValue func, object arg, R def) { if (!CanCallBack(func)) { return(def); } if (arg is ICbValue cbValue) { dummyArgumentsControl.EnableCbValue(cagt, cbValue); // 仮引数に引数を登録 } else { dummyArgumentsControl.Enable(cagt, (dynamic)arg); // 仮引数に引数を登録 } if (typeof(R) == typeof(ICbValue)) { ICbValue result = CallEvent(func, cagt); dummyArgumentsControl.Invalidated(cagt); // 仮引数後処理 return((R)result); } else { R result = (R)CallEvent(func, cagt).Data; dummyArgumentsControl.Invalidated(cagt); // 仮引数後処理 return(result); } }
/// <summary> /// コールバックを呼びます。 /// </summary> /// <param name="cagt">仮引数スタック</param> /// <param name="func">コールバック変数</param> protected void CallCallBack(DummyArgumentsStack cagt, ICbValue func) { CallEvent(func, cagt); }