コード例 #1
0
        private bool Interpolate(MethodDefinition method, ILProcessor ilgen, ILCursor cursor)
        {
            var str   = (string)cursor.current.Operand;
            var regex = new Regex("{{([a-zA-Z_0_9@]+)}}");

            var matches = regex.Matches(str);

            if (matches.Count == 0)
            {
                return(false);
            }

            var localMap    = new Dictionary <string, VariableDefinition>();
            var propertyMap = new Dictionary <string, PropertyDefinition>();
            var fieldMap    = new Dictionary <string, FieldDefinition>();

            foreach (var variable in method.Body.Variables)
            {
                localMap[variable.GetVariableName(method)] = variable;
            }
            foreach (var property in method.DeclaringType.Properties)
            {
                propertyMap[property.Name] = property;
            }
            foreach (var field in method.DeclaringType.Fields)
            {
                fieldMap[field.Name] = field;
            }

            var interpolatedVariable = new VariableDefinition(Global.module.TypeSystem.String);

            method.Body.Variables.Add(interpolatedVariable);

            var offset     = 0;
            var instOffset = cursor.current;

            cursor.Emit(
                ilgen.Create(OpCodes.Ldstr, ""));

            foreach (Match match in matches)
            {
                var     targetVariableName = match.Groups[1].Value;
                ILdable targetVariable     = null;

                if (localMap.ContainsKey(targetVariableName))
                {
                    targetVariable = new VariableLd(localMap[targetVariableName]);
                }
                else if (propertyMap.ContainsKey(targetVariableName))
                {
                    targetVariable = new PropertyLd(propertyMap[targetVariableName]);
                }
                else if (fieldMap.ContainsKey(targetVariableName))
                {
                    targetVariable = new FieldLd(fieldMap[targetVariableName]);
                }

                var prev = str.Substring(offset, match.Index - offset);

                // loc = loc + prev
                cursor.Emit(
                    ilgen.Create(OpCodes.Ldstr, prev),
                    ilgen.CreateCallStringConcat());

                bool toStringDirect = false;
                try
                {
                    var resolvedTargetType = targetVariable.type.Resolve();

                    if (resolvedTargetType.IsSealed ||
                        resolvedTargetType.IsValueType)
                    {
                        var toStringMethod = method.Module
                                             .Import(resolvedTargetType.Methods.First(x => x.Name == nameof(Object.ToString)));

                        if (targetVariable.type.IsValueType)
                        {
                            cursor.Emit(targetVariable.Lda(ilgen));
                        }
                        else
                        {
                            cursor.Emit(targetVariable.Ld(ilgen));
                        }

                        cursor.Emit(ilgen.Create(OpCodes.Call, toStringMethod));

                        toStringDirect = true;
                    }
                }
                catch (Exception e) { }

                if (toStringDirect == false)
                {
                    // loc = loc + capturedVar.ToString()
                    if (targetVariable.type.IsValueType)
                    {
                        // (object)capturedVar
                        cursor.Emit(targetVariable.Ld(ilgen));
                        cursor.Emit(ilgen.Create(OpCodes.Box, targetVariable.type));
                    }
                    else
                    {
                        cursor.Emit(targetVariable.Ld(ilgen));
                    }

                    cursor.Emit(ilgen.Create(OpCodes.Callvirt,
                                             Net2Resolver.GetMethod(nameof(Object), nameof(Object.ToString))));
                }

                cursor.Emit(ilgen.CreateCallStringConcat());

                offset = match.Index + match.Length;
            }

            cursor.Emit(ilgen.Create(OpCodes.Stloc, interpolatedVariable));

            // 남은 데이터
            if (offset != str.Length)
            {
                var prev = str.Substring(offset, str.Length - offset);

                cursor.Emit(
                    ilgen.Create(OpCodes.Ldloc, interpolatedVariable),
                    ilgen.Create(OpCodes.Ldstr, prev),
                    ilgen.CreateCallStringConcat(),
                    ilgen.Create(OpCodes.Stloc, interpolatedVariable));
            }

            cursor.Emit(ilgen.Create(OpCodes.Ldloc, interpolatedVariable));
            return(true);
        }