/// <summary> /// メソッド呼び出し処理を実装する /// </summary> /// <param name="col">スクリプトのルートノード</param> /// <param name="isReBuildMode">再構築か?(保存データからの復帰)</param> public override bool ImplAsset(MultiRootConnector col, bool isReBuildMode = false) { DummyArgumentsControl dummyArgumentsControl = new DummyArgumentsControl(col); string exTitle = GetGenericArgumentsString(col, isReBuildMode); return(ImplAsset(col, dummyArgumentsControl, exTitle)); }
/// <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="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="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> /// <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> /// <param name="col">スクリプトのルートノード</param> /// <param name="dummyArgumentsControl">仮引数管理</param> protected bool ImplAsset( MultiRootConnector col, DummyArgumentsControl dummyArgumentsControl, string exTitle) { Type classType = ClassType; string funcTitle = FuncTitle; Func <ICbValue> returnType = ReturnType; if (classType.IsGenericType) { // ジェネリッククラスの型を確定する var data = ReturnType().Data; if (data is CbGeneMethArg gmaType) { List <Type> argTypes = new List <Type>(); for (int i = 0; i < typeRequests.Count; ++i) { argTypes.Add(col.SelectedVariableType[i]); } //クラスの型を確定した型で差し替える classType = classType.MakeGenericType(argTypes.ToArray()); if (IsConstructor) { returnType = CbST.CbCreateTF(classType); if (funcTitle.Contains("<")) { // 確定した型情報に差し替える funcTitle = funcTitle.Substring(0, funcTitle.IndexOf("<")); } } } else if (CbSTUtils.HaveGenericParamater(classType)) { // ユーザー選択ではなく直接 self からコピーされた型の場合は、そのまま内容を登録する List <Type> argTypes = new List <Type>(); for (int i = 0; i < typeRequests.Count; ++i) { argTypes.Add(col.SelectedVariableType[i]); } //クラスの型を確定した型で差し替える classType = CbST.GetTypeEx(classType.FullName).MakeGenericType(argTypes.ToArray()); } } {// 返し値の型を差し替える var methodReturnType = returnType(); if (methodReturnType.MyType == typeof(CbClass <CbGeneMethArg>)) { // 未確定なジェネリック型を確定した型で差し替える // 引数の型を差し替える Type repType = GetConfirmedType(col, (CbGeneMethArg)methodReturnType.Data); returnType = CbST.CbCreateTF(repType); } } List <ICbValue> argumentTypeList = new List <ICbValue>(); if (ArgumentTypeList != null) { // 引数用の変数を用意する foreach (var node in ArgumentTypeList) { var argumentType = node.CreateArgument(); if (argumentType.MyType == typeof(CbClass <CbGeneMethArg>)) { // 未確定なジェネリック型を確定した型で差し替える // 引数の型を差し替える Type replaceArgumentType = GetConfirmedType(col, (CbGeneMethArg)argumentType.Data); argumentType = CbST.CbCreate(replaceArgumentType, argumentType.Name); } argumentTypeList.Add(argumentType); } } col.OldSpecification = oldSpecification; col.MakeFunction( funcTitle + exTitle, NodeHelpText, returnType, argumentTypeList, new Func <List <ICbValue>, DummyArgumentsStack, ICbValue>( (arguments, cagt) => { var ret = returnType(); if (dummyArgumentsControl != null && dummyArgumentsControl.IsInvalid(cagt)) { return(ret); // 実行環境が有効でない } ImplCallMethod(col, classType, dummyArgumentsControl, arguments, cagt, ret); return(ret); } ) ); argumentTypeList.Clear(); return(true); }
public DelegateFunction(CbFunc <T, RT> self, DummyArgumentsControl dummyArgumentsControl, DummyArgumentsStack cagt) : base(self, dummyArgumentsControl, cagt) { }
protected DelegateFunctionBase(CbFunc <T, RT> self, DummyArgumentsControl dummyArgumentsControl, DummyArgumentsStack cagt) { this.self = self; this.dummyArgumentsControl = dummyArgumentsControl; this.cagt = cagt; }