/// <summary> /// 変換メソッド:else /// </summary> /// <param name="item">C#解析結果</param> /// <param name="config">設定情報</param> /// <param name="indent">インデント数</param> /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param> /// <returns>TypeScript変換結果</returns> private string Convert(IItemElseClause item, Config config, int indent, List <string> otherScripts) { var result = new StringBuilder(); var indentSpace = GetIndentSpace(indent); // コメント result.Append(GetTypeScriptComments(item, indentSpace)); // 定義 if (item.Conditions.Any()) { result.AppendLine($"{indentSpace}else if ({ConvertConditions(item.Conditions)}) {{"); } else { result.AppendLine($"{indentSpace}else {{"); } // メンバー追加 foreach (var member in item.Block) { result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts)); } result.AppendLine($"{indentSpace}}}"); return(result.ToString()); }
/// <summary> /// 変換メソッド:switch /// </summary> /// <param name="item">C#解析結果</param> /// <param name="config">設定情報</param> /// <param name="indent">インデント数</param> /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param> /// <returns>TypeScript変換結果</returns> private string Convert(IItemSwitch item, Config config, int indent, List <string> otherScripts) { var result = new StringBuilder(); var indentSpace = GetIndentSpace(indent); // コメント result.Append(GetTypeScriptComments(item, indentSpace)); // caseがtypeチェックとローカルフィールド設定か否か var existsTypes = item.Cases.Where(caseItem => ExistsTypeCase(caseItem as IItemSwitchCase)).Any(); if (!existsTypes) { // 定義(switchのみ) result.AppendLine($"{indentSpace}switch ({ExpressionsToString(item.Conditions)}) {{"); // caseはインデントをインクリメント indent++; } // メンバー追加 foreach (var member in item.Cases) { result.Append(ConvertUtility.Convert(member, config, indent, otherScripts)); } if (!existsTypes) { // 定義(switchのみ) result.AppendLine($"{indentSpace}}}"); } return(result.ToString()); }
/// <summary> /// 変換メソッド:if /// </summary> /// <param name="item">C#解析結果</param> /// <param name="config">設定情報</param> /// <param name="indent">インデント数</param> /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param> /// <returns>TypeScript変換結果</returns> private string Convert(IItemIf item, Config config, int indent, List <string> otherScripts) { var result = new StringBuilder(); var indentSpace = GetIndentSpace(indent); // コメント result.Append(GetTypeScriptComments(item, indentSpace)); // 定義 result.AppendLine($"{indentSpace}if ({ConvertConditions(item.Conditions)}) {{"); // メンバー追加 foreach (var member in item.TrueBlock) { result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts)); } result.AppendLine($"{indentSpace}}}"); // else構文追加 foreach (var block in item.FalseBlocks) { result.Append(ConvertUtility.Convert(block, config, indent, otherScripts)); } return(result.ToString()); }
/// <summary> /// 変換メソッド:for /// </summary> /// <param name="item">C#解析結果</param> /// <param name="config">設定情報</param> /// <param name="indent">インデント数</param> /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param> /// <returns>TypeScript変換結果</returns> private string Convert(IItemFor item, Config config, int indent, List <string> otherScripts) { var result = new StringBuilder(); var indentSpace = GetIndentSpace(indent); // コメント result.Append(GetTypeScriptComments(item, indentSpace)); // 定義 var declarations = GetDeclarations(item); var letKeyword = item.IsVar ? "let " : string.Empty; var incrementors = item.Incrementors.Select(incrementor => ExpressionsToString(incrementor)); result.AppendLine($"{indentSpace}for ({letKeyword}{string.Join(", ", declarations)}; {ExpressionsToString(item.Conditions)}; {string.Join(", ", incrementors)}) {{"); // メンバー追加 foreach (var member in item.Members) { result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts)); } result.AppendLine($"{indentSpace}}}"); return(result.ToString()); }
/// <summary> /// 変換メソッド /// </summary> /// <param name="item">C#解析結果</param> /// <param name="indent">インデント数</param> /// <returns>TypeScript変換結果</returns> private string Convert(IItemClass item, Config config, int indent, List <string> otherScripts) { var result = new StringBuilder(); var classType = GetClassType(item); // 内部クラスの場合はインデント固定 if (classType == ClassType.Inner) { indent = 1; } var indentSpace = GetIndentSpace(indent); // クラスコメント result.Append(GetTypeScriptComments(item, indentSpace)); // クラス定義 result.Append(indentSpace); switch (classType) { case ClassType.Normal: result.Append($"{GetScope(item)}class {item.Name}{GetClassInfo(item)}"); break; case ClassType.Inner: result.Append($"export class {item.Name}{GetClassInfo(item)}"); break; } result.AppendLine(" {"); // メンバー追加 var members = item.Members; if (config.Mode.Value == OutputMode.Mode.WithoutMethod) { members = members.Where(member => member is IItemField || member is IItemProperty || member is IItemClass || member is IItemInterface).ToList(); } foreach (var member in members) { result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts)); } result.AppendLine($"{indentSpace}}}"); // 内部クラスの場合はotherScriptsに格納 if (classType == ClassType.Inner) { otherScripts.Add($"export namespace {GetParentClessName(item)} {{"); otherScripts.Add($"{result.ToString()}}}"); otherScripts.Add($""); // 親クラスのメンバーに含めない result.Clear(); } return(result.ToString()); }
public string Convert(IItemInterface item, Config config, int indent, List <string> otherScripts) { var result = new StringBuilder(); var indentSpace = GetIndentSpace(indent); // コメント result.Append(GetTypeScriptComments(item, indentSpace)); // インターフェイス定義 result.Append(indentSpace); result.Append($"{GetScope(item)}interface {item.Name}"); // ジェネリックスクラス if (item.GenericTypes.Any()) { result.Append("<"); result.Append(string.Join(", ", item.GenericTypes.Select(typeItem => GetTypeScriptType(typeItem)))); result.Append(">"); } // インターフェイスあり if (item.Interfaces.Any()) { var interfaceList = new List <string>(); foreach (var targetItemList in item.Interfaces) { // インターフェース名追加 interfaceList.Add(ExpressionsToString(targetItemList)); } result.Append(" implements "); result.Append(string.Join(", ", interfaceList.Select(typeItem => GetTypeScriptType(typeItem)))); } result.AppendLine(" {"); // メンバー追加 var members = item.Members; if (config.Mode.Value == OutputMode.Mode.WithoutMethod) { members = members.Where(member => member is IItemField || member is IItemProperty || member is IItemClass || member is IItemInterface).ToList(); } foreach (var member in members) { result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts)); } result.AppendLine($"{indentSpace}}}"); return(result.ToString()); }
public override ValueProvider <TResult> TryEvaluate(TContext context, string reference) { if (string.IsNullOrEmpty(reference) == false && (this.Settings.RequireSymbolForMemberReferences == false || reference[0] == '$')) { string error; MethodInfo method; var name = reference.TrimStart('$'); if (MemberFinder.Start(context.GetParentType()) .IsMethod() .HasNoParameters() .HasConvertableReturnType <TResult>() .IsNamed(name) .TryGetMember <MethodInfo>(out method, out error)) { bool isStatic = method.IsStatic(); Func <object, TResult> methodCaller; if (isStatic) { // TODO: Emit methodCaller = instance => { return(ConvertUtility.Convert <TResult>(method.Invoke(null, null))); }; } else { // TODO: Emit methodCaller = instance => { if (instance == null) { throw new NullReferenceException(); } return(ConvertUtility.Convert <TResult>(method.Invoke(instance, null))); }; } return(new FuncValueProvider <TResult>(context, isStatic == false, methodCaller)); } else { context.LogFailInfoFormat(this, " - {0} {1}", typeof(TResult).GetNiceName(), name); return(null); } } else { return(null); } }
/// <summary> /// 変換メソッド:case /// </summary> /// <param name="item">C#解析結果</param> /// <param name="config">設定情報</param> /// <param name="indent">インデント数</param> /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param> /// <returns>TypeScript変換結果</returns> private string Convert(IItemSwitchCase item, Config config, int indent, List <string> otherScripts) { var result = new StringBuilder(); var indentSpace = GetIndentSpace(indent); // コメント result.Append(GetTypeScriptComments(item, indentSpace)); // typeチェックとローカルフィールド設定か否か var existsTypes = ExistsTypeCase(item); // 定義 case か if の出力分岐 if (existsTypes) { result.Append(CreateCaseIf(item, indent)); } else { // case foreach (var label in item.Labels) { result.Append($"{indentSpace}"); if (label.First().TypeName != "Default") { result.Append("case "); } result.AppendLine($"{ExpressionsToString(label)}:"); } } // メンバー追加 foreach (var member in item.Members) { // if構文に変化した場合はbreakを除外 if (existsTypes && member is IItemBreak) { continue; } result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts)); } if (existsTypes) { // if : ブロック終了 result.AppendLine($"{indentSpace}}}"); } return(result.ToString()); }
/// <summary> /// プロパティのset/get用Typescriptを返す /// </summary> /// <param name="accessorItem">set/get用のアイテム</param> /// <param name="config">設定情報</param> /// <param name="indent">インデント数</param> /// <param name="scope">スコープ名</param> /// <param name="propertyName">プロパティ名</param> /// <param name="propertyType">プロパティの型</param> /// <param name="refTarget">参照名(インスタンス参照の場合はthis)</param> /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param> /// <returns>set/get用Typescriptの文字列</returns> private string GetAccessorString(IAnalyzeItem accessorItem, Config config, int indent, string scope, string propertyName, string propertyType, string refTarget, List <string> otherScripts) { var indentSpace = GetIndentSpace(indent); var result = new StringBuilder(); var notExistsMember = true; if (accessorItem.Members.Any()) { notExistsMember = false; } // set/getの設定 var accessorItemName = accessorItem.Name.ToLower(CultureInfo.CurrentCulture); switch (accessorItemName) { case "set": result.AppendLine($"{indentSpace}{scope}set {propertyName}(value: {propertyType}) {{"); if (notExistsMember) { result.AppendLine($"{GetIndentSpace(indent + 1)}{refTarget}._{propertyName}_ = value;"); } break; case "get": result.AppendLine($"{indentSpace}{scope}get {propertyName}(): {propertyType} {{"); if (notExistsMember) { result.AppendLine($"{GetIndentSpace(indent + 1)}return {refTarget}._{propertyName}_;"); } break; default: return(result.ToString()); } // メンバー追加 foreach (var member in accessorItem.Members) { result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts)); } result.AppendLine($"{indentSpace}}}"); return(result.ToString()); }
/// <summary> /// 変換メソッド /// </summary> /// <param name="item">C#解析結果</param> /// <param name="config">設定情報</param> /// <param name="indent">インデント数</param> /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param> /// <returns>TypeScript変換結果</returns> private string Convert(IItemLocalFunction item, Config config, int indent, List <string> otherScripts) { var result = new StringBuilder(); var indentSpace = GetIndentSpace(indent); // コメント result.Append(GetTypeScriptComments(item, indentSpace)); // パラメータ取得 var args = new List <string>(); foreach (var arg in item.Args) { args.Add($"{arg.name}: {ExpressionsToString(arg.expressions)}"); } // ジェネリックスクラス var genericTypes = new StringBuilder(); if (item.GenericTypes.Any()) { genericTypes.Append("<"); genericTypes.Append(string.Join(", ", item.GenericTypes.Select(typeItem => GetTypeScriptType(typeItem)))); genericTypes.Append(">"); } // 定義 result.Append($"{indentSpace}let {item.Name} = {genericTypes.ToString()}("); result.Append(string.Join(", ", args)); result.AppendLine($"): {ExpressionsToString(item.MethodTypes)} => {{"); // メンバー追加 foreach (var member in item.Members) { result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts)); } result.AppendLine($"{indentSpace}}};"); return(result.ToString()); }
/// <summary> /// 変換メソッド:while /// </summary> /// <param name="item">C#解析結果</param> /// <param name="config">設定情報</param> /// <param name="indent">インデント数</param> /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param> /// <returns>TypeScript変換結果</returns> private string Convert(IItemWhile item, Config config, int indent, List <string> otherScripts) { var result = new StringBuilder(); var indentSpace = GetIndentSpace(indent); // コメント result.Append(GetTypeScriptComments(item, indentSpace)); // 定義 result.AppendLine($"{indentSpace}while ({ExpressionsToString(item.Conditions)}) {{"); // メンバー追加 foreach (var member in item.Members) { result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts)); } result.AppendLine($"{indentSpace}}}"); return(result.ToString()); }
/// <summary> /// 変換メソッド:foreach /// </summary> /// <param name="item">C#解析結果</param> /// <param name="config">設定情報</param> /// <param name="indent">インデント数</param> /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param> /// <returns>TypeScript変換結果</returns> private string Convert(IItemForEach item, Config config, int indent, List <string> otherScripts) { var result = new StringBuilder(); var indentSpace = GetIndentSpace(indent); // コメント result.Append(GetTypeScriptComments(item, indentSpace)); // 定義 var isMultiParams = false; var multiParamLocalName = string.Empty; var localName = ExpressionsToString(item.Local); if (item.CollectionTypes.First().Name == "Dictionary") { multiParamLocalName = localName; isMultiParams = true; localName = "[k, v]"; } result.AppendLine($"{indentSpace}for (let {localName} of {ExpressionsToString(item.Collection)}) {{"); // 複数要素の場合はローカル変数作成 if (isMultiParams) { result.AppendLine($"{GetIndentSpace(indent + 1)}let {multiParamLocalName} = {{ \"Key\": k, \"Value\": v }};"); } // メンバー追加 foreach (var member in item.Members) { result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts)); } result.AppendLine($"{indentSpace}}}"); return(result.ToString()); }
/// <summary> /// 変換メソッド /// </summary> /// <param name="item">C#解析結果</param> /// <param name="indent">インデント数</param> /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param> /// <returns>TypeScript変換結果</returns> private string Convert(IItemConstructor item, Config config, int indent, List <string> otherScripts) { var result = new StringBuilder(); var indentSpace = GetIndentSpace(indent); // クラス情報を取得 var classInstanse = item.Parent as IItemClass; var className = classInstanse.Name; var targetIndex = 1; var targetItems = classInstanse.Members.Where(member => member is IItemConstructor) .Select(member => (index: targetIndex++, item: member as IItemConstructor)).ToList(); var existSuper = classInstanse.SuperClass.Any(); var isOverload = targetItems.Count() > 1; // 複数コンストラクタの存在確認 var indexValue = string.Empty; if (isOverload) { // インデックスの設定 foreach (var targetItem in targetItems) { if (targetItem.item == item) { indexValue = $"{targetItem.index}"; } } } // コメント result.Append(GetTypeScriptComments(item, indentSpace)); // パラメータ取得 var args = new List <string>(); foreach (var arg in item.Args) { args.Add($"{arg.name}: {ExpressionsToString(arg.expressions)}"); } // 定義 var scope = GetScope(item); if (scope == "public ") { scope = string.Empty; } if (isOverload) { scope = "private "; } result.Append($"{indentSpace}{scope}{BaseMethodName}{indexValue}"); result.Append("("); result.Append(string.Join(", ", args)); result.Append(")"); result.AppendLine(" {"); // メンバー追加 if (existSuper) { // スーパークラスありの場合はコンストラクタを呼び出す result.Append($"{GetIndentSpace(indent + 1)}base("); result.Append(string.Join(", ", item.BaseArgs)); result.AppendLine(");"); } foreach (var member in item.Members) { result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts)); } result.AppendLine($"{indentSpace}}}"); // 複数メソッドで最終メソッドの場合は総括メソッドを作成する if (isOverload && targetItems.Last().item == item) { // 総合メソッド内処理用文字列 var methodResult = new StringBuilder(); // パラメータ数のリスト取得 var paramCounts = targetItems.Select(member => member.item.Args.Count); var existsNoneParam = paramCounts.Min() <= 0; var maxParamCount = paramCounts.Max(); // パラメータリストを生成 var methodArgs = new Dictionary <int, List <string> >(); for (var index = 1; index <= maxParamCount; index++) { methodArgs.Add(index, new List <string>()); } // メソッドパラメータの格納とメソッド内処理の作成 foreach (var targetItem in targetItems) { // 1メソッドのパラメータ取得 var argIndex = 1; var ifConditions = new List <string>(); var callMethodParams = new List <string>(); foreach (var arg in targetItem.item.Args) { var expressionsValue = ExpressionsToString(arg.expressions); // メソッドパラメータに追加 if (!methodArgs[argIndex].Contains(expressionsValue)) { methodArgs[argIndex].Add(expressionsValue); } // メソッド内条件 ifConditions.Add(GetCondition(argIndex, expressionsValue)); // 呼び出しメソッドのパラメータ callMethodParams.Add($"param{argIndex}"); argIndex++; } // メソッド内条件の追加 while (argIndex <= maxParamCount) { ifConditions.Add(GetCondition(argIndex, "undefined")); argIndex++; } // メソッド内処理の追加 var methodSpace = GetIndentSpace(indent + 1); methodResult.AppendLine($"{methodSpace}if ({string.Join(" && ", ifConditions)}) {{"); methodResult.Append($"{GetIndentSpace(indent + 2)}this.{BaseMethodName}{targetItem.index}"); methodResult.Append("("); methodResult.Append(string.Join(", ", callMethodParams)); methodResult.AppendLine(");"); methodResult.AppendLine($"{GetIndentSpace(indent + 2)}return;"); methodResult.AppendLine($"{methodSpace}}}"); } // 総合メソッドの作成 scope = GetScope(item); if (scope == "public ") { scope = string.Empty; } result.Append($"{indentSpace}{scope}{BaseMethodName}("); for (var index = 1; index <= maxParamCount; index++) { if (index > 1) { result.Append(", "); } result.Append($"param{index}"); if (existsNoneParam) { result.Append("?"); } result.Append($": {string.Join(" | ", methodArgs[index])}"); } result.AppendLine(") {"); result.Append(methodResult.ToString()); result.AppendLine($"{indentSpace}}}"); } return(result.ToString()); }
/// <summary> /// 変換メソッド メイン処理(class) /// </summary> /// <param name="parentInstanse">親インスタンス</param> /// <param name="item">C#解析結果</param> /// <param name="config">設定情報</param> /// <param name="indent">インデント数</param> /// <param name="otherScripts">その他のスクリプト(内部クラスなど)</param> /// <returns>TypeScript変換結果</returns> private string ConvertMain(IItemClass parentInstanse, IItemMethod item, Config config, int indent, List <string> otherScripts) { // 親インスタンスがnullの場合はそのまま終了 if (parentInstanse is null) { return(string.Empty); } var result = new StringBuilder(); var indentSpace = GetIndentSpace(indent); // メソッド名 string BaseMethodName = item.Name; // クラス情報(親インスタンス)を取得 var className = parentInstanse.Name; var targetIndex = 1; var targetItems = parentInstanse.Members.Where(member => member is IItemMethod && member.Name == BaseMethodName) .Select(member => (index: targetIndex++, item: member as IItemMethod)).ToList(); var isOverload = targetItems.Count() > 1; var returnType = ExpressionsToString(item.MethodTypes); var isReturn = returnType != "void"; // 複数コンストラクタの存在確認 var indexValue = string.Empty; if (isOverload) { // インデックスの設定 foreach (var targetItem in targetItems) { if (targetItem.item == item) { indexValue = $"{targetItem.index}"; } } } // コメント result.Append(GetTypeScriptComments(item, indentSpace)); // パラメータ取得 var args = new List <string>(); foreach (var arg in item.Args) { args.Add($"{arg.name}: {ExpressionsToString(arg.expressions)}"); } // 定義 var scope = GetScope(item); if (isOverload) { scope = "private "; } if (item.Modifiers.Contains("static")) { scope += "static "; } result.Append($"{indentSpace}{scope}{BaseMethodName}{indexValue}"); // ジェネリックスクラス if (item.GenericTypes.Any()) { result.Append("<"); result.Append(string.Join(", ", item.GenericTypes.Select(typeItem => GetTypeScriptType(typeItem)))); result.Append(">"); } result.Append("("); result.Append(string.Join(", ", args)); result.Append($"): {returnType}"); result.AppendLine(" {"); // メンバー追加 foreach (var member in item.Members) { result.Append(ConvertUtility.Convert(member, config, indent + 1, otherScripts)); } result.AppendLine($"{indentSpace}}}"); // 複数メソッドで最終メソッドの場合は総括メソッドを作成する if (isOverload && targetItems.Last().item == item) { // 総合メソッド内処理用文字列 var methodResult = new StringBuilder(); // パラメータ数のリスト取得 var paramCounts = targetItems.Select(member => member.item.Args.Count); var existsNoneParam = paramCounts.Min() <= 0; var maxParamCount = paramCounts.Max(); // 戻り値の取得 var retrunTypes = targetItems. Select(returnTypeItem => ExpressionsToString(returnTypeItem.item.MethodTypes)). Distinct(); var isMultiReturnType = retrunTypes.Count() > 1; // パラメータリストを生成 var methodArgs = new Dictionary <int, List <string> >(); for (var index = 1; index <= maxParamCount; index++) { methodArgs.Add(index, new List <string>()); } // メソッドパラメータの格納とメソッド内処理の作成 foreach (var targetItem in targetItems) { // 1メソッドのパラメータ取得 var argIndex = 1; var ifConditions = new List <string>(); var callMethodParams = new List <string>(); foreach (var arg in targetItem.item.Args) { var expressionsValue = ExpressionsToString(arg.expressions); // メソッドパラメータに追加 if (!methodArgs[argIndex].Contains(expressionsValue)) { methodArgs[argIndex].Add(expressionsValue); } // メソッド内条件 ifConditions.Add(GetCondition(argIndex, expressionsValue)); // 呼び出しメソッドのパラメータ callMethodParams.Add($"param{argIndex}"); argIndex++; } // メソッド内条件の追加 while (argIndex <= maxParamCount) { ifConditions.Add(GetCondition(argIndex, "undefined")); argIndex++; } // メソッド内処理の追加 var methodSpace = GetIndentSpace(indent + 1); methodResult.AppendLine($"{methodSpace}if ({string.Join(" && ", ifConditions)}) {{"); methodResult.Append($"{GetIndentSpace(indent + 2)}"); if (isMultiReturnType) { methodResult.Append($"return "); } methodResult.Append($"this.{BaseMethodName}{targetItem.index}"); methodResult.Append("("); methodResult.Append(string.Join(", ", callMethodParams)); methodResult.AppendLine(");"); if (!isMultiReturnType) { methodResult.AppendLine($"{GetIndentSpace(indent + 2)}return;"); } methodResult.AppendLine($"{methodSpace}}}"); } // 総合メソッドの作成 result.Append($"{indentSpace}{GetScope(item)}{BaseMethodName}("); // パラメータ設定 for (var index = 1; index <= maxParamCount; index++) { if (index > 1) { result.Append(", "); } result.Append($"param{index}"); if (existsNoneParam) { result.Append("?"); } result.Append($": {string.Join(" | ", methodArgs[index])}"); } // 戻り値 var methodType = string.Join(" | ", retrunTypes); //if(isMultiReturnType) //{ // methodType = "any"; //} result.Append($"): {methodType}"); result.AppendLine(" {"); result.Append(methodResult.ToString()); result.AppendLine($"{GetIndentSpace(indent + 1)}throw new Error('Error');"); result.AppendLine($"{indentSpace}}}"); } return(result.ToString()); }
public override ValueProvider <TResult> TryEvaluate(TContext context, string reference) { if (string.IsNullOrEmpty(reference) == false && (this.Settings.RequireSymbolForMemberReferences == false || reference[0] == '$')) { string name = reference.TrimStart('$'); var finder = MemberFinder.Start(context.GetParentType()) .HasNoParameters() .HasConvertableReturnType <TResult>() .IsNamed(name); if (this.IsStatic(context)) { finder = finder.IsStatic(); } string error; MemberInfo member; if (finder.TryGetMember(out member, out error)) { bool isStatic = member.IsStatic(); Func <object, TResult> getter; if (isStatic) { if (member is MethodInfo) { // TODO: Emit. var method = member as MethodInfo; getter = instance => { return(ConvertUtility.Convert <TResult>(method.Invoke(null, null))); }; } else { // TODO: Emit getter = instance => { return(ConvertUtility.Convert <TResult>(member.GetMemberValue(null))); }; } } else { if (member is MethodInfo) { // TODO: Emit. var method = member as MethodInfo; getter = instance => { if (instance == null) { throw new NullReferenceException("Parent instance missing."); } return(ConvertUtility.Convert <TResult>(method.Invoke(instance, null))); }; } else { // TODO: Emit getter = instance => { if (instance == null) { throw new NullReferenceException("Parent instance missing."); } return(ConvertUtility.Convert <TResult>(member.GetMemberValue(instance))); }; } } return(new FuncValueProvider <TResult>(context, isStatic == false, getter)); //if (member.IsStatic()) //{ // if (member is MethodInfo) // { // var method = member as MethodInfo; // return new FuncValueProvider<TResult>(context, false, o => ConvertUtility.Convert<TResult>(method.Invoke(null, null))); // } // // TODO: Can PropertyInfo and FieldInfo be straight as one? // else if (member is PropertyInfo) // { // EmitUtilities.CreateGetter // } // else if (member is FieldInfo) // { // var field = member as FieldInfo; // //EmitUtilities.CreateStaticFieldGetter // //return new FuncValueProvider<TResult>(context, false, o => ConvertUtility.Convert<TResult>(member.GetMemberValue(null))); // if (typeof(TResult).IsAssignableFrom(field.GetReturnType())) // { // var getter = EmitUtilities.CreateStaticFieldGetter<TResult>(field); // return new StaticFuncValueProvider<TResult>(context, getter); // } // else // { // var getter = EmitUtilities.CreateWeakStaticFieldGetter(field); // return new StaticFuncValueProvider<TResult>(context, () => ConvertUtility.Convert<TResult>(getter())); // } // } // else // { // throw new InvalidOperationException("Hang on that's not right."); // } //} //else //{ // return new MemberValueProvider<TResult>(context, member); //} } else { context.LogFailInfo(this, "Cannot find a member in type '" + context.GetParentType().GetNiceName() + "' named '" + name + "' with a return type castable to '" + typeof(TResult).GetNiceName() + "'"); } } return(null); }
public override ValueProvider <TResult> TryEvaluate(TContext context, string reference) { if (string.IsNullOrEmpty(reference) == false && reference[0] == '@') { string expression = reference.Substring(1); bool isStatic = this.IsStatic(context); var parameters = context.GetExpressionParameters(); if (parameters != null && parameters.Length > 0) { string[] pNames = new string[parameters.Length]; Type[] pTypes = new Type[parameters.Length]; Func <object>[] pGetters = new Func <object> [parameters.Length]; for (int i = 0; i < parameters.Length; i++) { pNames[i] = parameters[i].Name; pTypes[i] = parameters[i].Type; pGetters[i] = parameters[i].GetValue; } string error; var method = ExpressionUtility.ParseExpression(expression, isStatic, context.GetParentType(), pTypes, pNames, out error); if (!method.Method.ReturnType.IsCastableTo(typeof(TResult))) { error = "The expression '" + expression + "' evaluates to type '" + method.Method.ReturnType.GetNiceName() + "', which cannot be cast to expected type '" + typeof(TResult).GetNiceName() + "'."; } if (error != null) { context.LogFailInfo(this, error); return(null); } else if (isStatic) { object[] valueBuffer = new object[parameters.Length]; return(new FuncValueProvider <TResult>(context, false, instance => ConvertUtility.Convert <TResult>(method.DynamicInvoke(GetValues(valueBuffer, pGetters))))); } else { object[] valueBuffer = new object[parameters.Length + 1]; return(new FuncValueProvider <TResult>(context, true, instance => ConvertUtility.Convert <TResult>(method.DynamicInvoke(GetValues(valueBuffer, instance, pGetters))))); } } else { string error; var method = ExpressionUtility.ParseExpression(expression, isStatic, context.GetParentType(), out error); if (!method.Method.ReturnType.IsCastableTo(typeof(TResult))) { error = "The expression '" + expression + "' evaluates to type '" + method.Method.ReturnType.GetNiceName() + "', which cannot be cast to expected type '" + typeof(TResult).GetNiceName() + "'."; } if (error != null) { context.LogFailInfo(this, error); return(null); } else if (isStatic) { return(new FuncValueProvider <TResult>(context, false, instance => ConvertUtility.Convert <TResult>(method.DynamicInvoke()))); } else { return(new FuncValueProvider <TResult>(context, true, instance => ConvertUtility.Convert <TResult>(method.DynamicInvoke(instance)))); } } } else { return(null); } }