diff options
author | Stephane Delcroix <stephane@delcroix.org> | 2016-09-27 20:10:39 +0200 |
---|---|---|
committer | Jason Smith <jason.smith@xamarin.com> | 2016-09-27 11:10:39 -0700 |
commit | 3e0ee965d710768f1c434b469f8c1c8371b7659a (patch) | |
tree | 1c5fe29f542e098ec68f3f0a029df380e07c41e6 /Xamarin.Forms.Build.Tasks | |
parent | 0f7b22f49d767c3ae522641c324e7ef6928719b4 (diff) | |
download | xamarin-forms-3e0ee965d710768f1c434b469f8c1c8371b7659a.tar.gz xamarin-forms-3e0ee965d710768f1c434b469f8c1c8371b7659a.tar.bz2 xamarin-forms-3e0ee965d710768f1c434b469f8c1c8371b7659a.zip |
[Xaml] more primitive types (#385)
* [Xaml] more builtin conversion, and more type primitives
* [XamlC] more builtin conversion, more type primitives
Diffstat (limited to 'Xamarin.Forms.Build.Tasks')
-rw-r--r-- | Xamarin.Forms.Build.Tasks/CreateObjectVisitor.cs | 410 | ||||
-rw-r--r-- | Xamarin.Forms.Build.Tasks/NodeILExtensions.cs | 72 |
2 files changed, 272 insertions, 210 deletions
diff --git a/Xamarin.Forms.Build.Tasks/CreateObjectVisitor.cs b/Xamarin.Forms.Build.Tasks/CreateObjectVisitor.cs index 33a9a7f5..6d6405e1 100644 --- a/Xamarin.Forms.Build.Tasks/CreateObjectVisitor.cs +++ b/Xamarin.Forms.Build.Tasks/CreateObjectVisitor.cs @@ -317,18 +317,22 @@ namespace Xamarin.Forms.Build.Tasks if (node.NamespaceURI != "clr-namespace:System;assembly=mscorlib") return false; var name = node.XmlType.Name.Split(':')[1]; - if (name == "Boolean" || - name == "String" || - name == "Char" || - name == "Decimal" || - name == "Single" || - name == "Double" || - name == "Byte" || - name == "Int16" || - name == "Int32" || - name == "Int64" || - name == "TimeSpan" || - name == "Uri") + if (name == "SByte" || + name == "Int16" || + name == "Int32" || + name == "Int64" || + name == "Byte" || + name == "UInt16" || + name == "UInt32" || + name == "UInt64" || + name == "Single" || + name == "Double" || + name == "Boolean" || + name == "String" || + name == "Char" || + name == "Decimal" || + name == "TimeSpan" || + name == "Uri") return true; return false; } @@ -338,190 +342,206 @@ namespace Xamarin.Forms.Build.Tasks var hasValue = node.CollectionItems.Count == 1 && node.CollectionItems[0] is ValueNode && ((ValueNode)node.CollectionItems[0]).Value is string; var valueString = hasValue ? ((ValueNode)node.CollectionItems[0]).Value as string : string.Empty; - switch (typedef.FullName) - { - case "System.Boolean": - bool outbool; - if (hasValue && bool.TryParse(valueString, out outbool)) - yield return Instruction.Create(outbool ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); - else - yield return Instruction.Create(OpCodes.Ldc_I4_0); - break; - case "System.String": + switch (typedef.FullName) { + case "System.SByte": + sbyte outsbyte; + if (hasValue && sbyte.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outsbyte)) + yield return Instruction.Create(OpCodes.Ldc_I4, (int)outsbyte); + else + yield return Instruction.Create(OpCodes.Ldc_I4, 0x00); + break; + case "System.Int16": + short outshort; + if (hasValue && short.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outshort)) + yield return Instruction.Create(OpCodes.Ldc_I4, outshort); + else + yield return Instruction.Create(OpCodes.Ldc_I4, 0x00); + break; + case "System.Int32": + int outint; + if (hasValue && int.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outint)) + yield return Instruction.Create(OpCodes.Ldc_I4, outint); + else + yield return Instruction.Create(OpCodes.Ldc_I4, 0x00); + break; + case "System.Int64": + long outlong; + if (hasValue && long.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outlong)) + yield return Instruction.Create(OpCodes.Ldc_I8, outlong); + else + yield return Instruction.Create(OpCodes.Ldc_I8, 0L); + break; + case "System.Byte": + byte outbyte; + if (hasValue && byte.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outbyte)) + yield return Instruction.Create(OpCodes.Ldc_I4, (int)outbyte); + else + yield return Instruction.Create(OpCodes.Ldc_I4, 0x00); + break; + case "System.UInt16": + short outushort; + if (hasValue && short.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outushort)) + yield return Instruction.Create(OpCodes.Ldc_I4, outushort); + else + yield return Instruction.Create(OpCodes.Ldc_I4, 0x00); + break; + case "System.UInt32": + int outuint; + if (hasValue && int.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outuint)) + yield return Instruction.Create(OpCodes.Ldc_I4, outuint); + else + yield return Instruction.Create(OpCodes.Ldc_I4, 0x00); + break; + case "System.UInt64": + long outulong; + if (hasValue && long.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outulong)) + yield return Instruction.Create(OpCodes.Ldc_I8, outulong); + else + yield return Instruction.Create(OpCodes.Ldc_I8, 0L); + break; + case "System.Boolean": + bool outbool; + if (hasValue && bool.TryParse(valueString, out outbool)) + yield return Instruction.Create(outbool ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); + else + yield return Instruction.Create(OpCodes.Ldc_I4_0); + break; + case "System.String": + yield return Instruction.Create(OpCodes.Ldstr, valueString); + break; + case "System.Object": + var ctorinfo = + Context.Body.Method.Module.TypeSystem.Object.Resolve() + .Methods.FirstOrDefault(md => md.IsConstructor && !md.HasParameters); + var ctor = Context.Body.Method.Module.Import(ctorinfo); + yield return Instruction.Create(OpCodes.Newobj, ctor); + break; + case "System.Char": + char outchar; + if (hasValue && char.TryParse(valueString, out outchar)) + yield return Instruction.Create(OpCodes.Ldc_I4, outchar); + else + yield return Instruction.Create(OpCodes.Ldc_I4, 0x00); + break; + case "System.Decimal": + decimal outdecimal; + if (hasValue && decimal.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outdecimal)) { + var vardef = new VariableDefinition(Context.Body.Method.Module.Import(typeof(decimal))); + Context.Body.Variables.Add(vardef); + //Use an extra temp var so we can push the value to the stack, just like other cases + // IL_0003: ldstr "adecimal" + // IL_0008: ldc.i4.s 0x6f + // IL_000a: call class [mscorlib]System.Globalization.CultureInfo class [mscorlib]System.Globalization.CultureInfo::get_InvariantCulture() + // IL_000f: ldloca.s 0 + // IL_0011: call bool valuetype [mscorlib]System.Decimal::TryParse(string, valuetype [mscorlib]System.Globalization.NumberStyles, class [mscorlib]System.IFormatProvider, [out] valuetype [mscorlib]System.Decimal&) + // IL_0016: pop yield return Instruction.Create(OpCodes.Ldstr, valueString); - break; - case "System.Object": - var ctorinfo = - Context.Body.Method.Module.TypeSystem.Object.Resolve() - .Methods.FirstOrDefault(md => md.IsConstructor && !md.HasParameters); - var ctor = Context.Body.Method.Module.Import(ctorinfo); - yield return Instruction.Create(OpCodes.Newobj, ctor); - break; - case "System.Char": - char outchar; - if (hasValue && char.TryParse(valueString, out outchar)) - yield return Instruction.Create(OpCodes.Ldc_I4, outchar); - else - yield return Instruction.Create(OpCodes.Ldc_I4, 0x00); - break; - case "System.Decimal": - decimal outdecimal; - if (hasValue && decimal.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outdecimal)) - { - var vardef = new VariableDefinition(Context.Body.Method.Module.Import(typeof (decimal))); - Context.Body.Variables.Add(vardef); - //Use an extra temp var so we can push the value to the stack, just like other cases - // IL_0003: ldstr "adecimal" - // IL_0008: ldc.i4.s 0x6f - // IL_000a: call class [mscorlib]System.Globalization.CultureInfo class [mscorlib]System.Globalization.CultureInfo::get_InvariantCulture() - // IL_000f: ldloca.s 0 - // IL_0011: call bool valuetype [mscorlib]System.Decimal::TryParse(string, valuetype [mscorlib]System.Globalization.NumberStyles, class [mscorlib]System.IFormatProvider, [out] valuetype [mscorlib]System.Decimal&) - // IL_0016: pop - yield return Instruction.Create(OpCodes.Ldstr, valueString); - yield return Instruction.Create(OpCodes.Ldc_I4, 0x6f); //NumberStyles.Number - var getInvariantInfo = - Context.Body.Method.Module.Import(typeof (CultureInfo)) - .Resolve() - .Properties.FirstOrDefault(pd => pd.Name == "InvariantCulture") - .GetMethod; - var getInvariant = Context.Body.Method.Module.Import(getInvariantInfo); - yield return Instruction.Create(OpCodes.Call, getInvariant); - yield return Instruction.Create(OpCodes.Ldloca, vardef); - var tryParseInfo = - Context.Body.Method.Module.Import(typeof (decimal)) - .Resolve() - .Methods.FirstOrDefault(md => md.Name == "TryParse" && md.Parameters.Count == 4); - var tryParse = Context.Body.Method.Module.Import(tryParseInfo); - yield return Instruction.Create(OpCodes.Call, tryParse); - yield return Instruction.Create(OpCodes.Pop); - yield return Instruction.Create(OpCodes.Ldloc, vardef); - } - else - { - yield return Instruction.Create(OpCodes.Ldc_I4_0); - var decimalctorinfo = - Context.Body.Method.Module.Import(typeof (decimal)) - .Resolve() - .Methods.FirstOrDefault( - md => md.IsConstructor && md.Parameters.Count == 1 && md.Parameters[0].ParameterType.FullName == "System.Int32"); - var decimalctor = Context.Body.Method.Module.Import(decimalctorinfo); - yield return Instruction.Create(OpCodes.Newobj, decimalctor); - } - break; - case "System.Single": - float outfloat; - if (hasValue && float.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outfloat)) - yield return Instruction.Create(OpCodes.Ldc_R4, outfloat); - else - yield return Instruction.Create(OpCodes.Ldc_R4, 0f); - break; - case "System.Double": - double outdouble; - if (hasValue && double.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outdouble)) - yield return Instruction.Create(OpCodes.Ldc_R8, outdouble); - else - yield return Instruction.Create(OpCodes.Ldc_R8, 0d); - break; - case "System.Byte": - byte outbyte; - if (hasValue && byte.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outbyte)) - yield return Instruction.Create(OpCodes.Ldc_I4, (int)outbyte); - else - yield return Instruction.Create(OpCodes.Ldc_I4, 0x00); - break; - case "System.Int16": - short outshort; - if (hasValue && short.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outshort)) - yield return Instruction.Create(OpCodes.Ldc_I4, outshort); - else - yield return Instruction.Create(OpCodes.Ldc_I4, 0x00); - break; - case "System.Int32": - int outint; - if (hasValue && int.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outint)) - yield return Instruction.Create(OpCodes.Ldc_I4, outint); - else - yield return Instruction.Create(OpCodes.Ldc_I4, 0x00); - break; - case "System.Int64": - long outlong; - if (hasValue && long.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outlong)) - yield return Instruction.Create(OpCodes.Ldc_I8, outlong); - else - yield return Instruction.Create(OpCodes.Ldc_I8, 0L); - break; - case "System.TimeSpan": - TimeSpan outspan; - if (hasValue && TimeSpan.TryParse(valueString, CultureInfo.InvariantCulture, out outspan)) - { - var vardef = new VariableDefinition(Context.Body.Method.Module.Import(typeof (TimeSpan))); - Context.Body.Variables.Add(vardef); - //Use an extra temp var so we can push the value to the stack, just like other cases - yield return Instruction.Create(OpCodes.Ldstr, valueString); - var getInvariantInfo = - Context.Body.Method.Module.Import(typeof (CultureInfo)) - .Resolve() - .Properties.FirstOrDefault(pd => pd.Name == "InvariantCulture") - .GetMethod; - var getInvariant = Context.Body.Method.Module.Import(getInvariantInfo); - yield return Instruction.Create(OpCodes.Call, getInvariant); - yield return Instruction.Create(OpCodes.Ldloca, vardef); - var tryParseInfo = - Context.Body.Method.Module.Import(typeof (TimeSpan)) - .Resolve() - .Methods.FirstOrDefault(md => md.Name == "TryParse" && md.Parameters.Count == 3); - var tryParse = Context.Body.Method.Module.Import(tryParseInfo); - yield return Instruction.Create(OpCodes.Call, tryParse); - yield return Instruction.Create(OpCodes.Pop); - yield return Instruction.Create(OpCodes.Ldloc, vardef); - } - else - { - yield return Instruction.Create(OpCodes.Ldc_I8, 0L); - var timespanctorinfo = - Context.Body.Method.Module.Import(typeof (TimeSpan)) - .Resolve() - .Methods.FirstOrDefault( - md => md.IsConstructor && md.Parameters.Count == 1 && md.Parameters[0].ParameterType.FullName == "System.Int64"); - var timespanctor = Context.Body.Method.Module.Import(timespanctorinfo); - yield return Instruction.Create(OpCodes.Newobj, timespanctor); - } - break; - case "System.Uri": - Uri outuri; - if (hasValue && Uri.TryCreate(valueString, UriKind.RelativeOrAbsolute, out outuri)) - { - var vardef = new VariableDefinition(Context.Body.Method.Module.Import(typeof (Uri))); - Context.Body.Variables.Add(vardef); - //Use an extra temp var so we can push the value to the stack, just like other cases - yield return Instruction.Create(OpCodes.Ldstr, valueString); - yield return Instruction.Create(OpCodes.Ldc_I4, (int)UriKind.RelativeOrAbsolute); - yield return Instruction.Create(OpCodes.Ldloca, vardef); - var tryCreateInfo = - Context.Body.Method.Module.Import(typeof (Uri)) - .Resolve() - .Methods.FirstOrDefault(md => md.Name == "TryCreate" && md.Parameters.Count == 3); - var tryCreate = Context.Body.Method.Module.Import(tryCreateInfo); - yield return Instruction.Create(OpCodes.Call, tryCreate); - yield return Instruction.Create(OpCodes.Pop); - yield return Instruction.Create(OpCodes.Ldloc, vardef); - } - else - yield return Instruction.Create(OpCodes.Ldnull); - break; - default: - var defaultctorinfo = typedef.Methods.FirstOrDefault(md => md.IsConstructor && !md.HasParameters); - if (defaultctorinfo != null) - { - var defaultctor = Context.Body.Method.Module.Import(defaultctorinfo); - yield return Instruction.Create(OpCodes.Newobj, defaultctor); - } - else - { - //should never happen. but if it does, this prevents corrupting the IL stack - yield return Instruction.Create(OpCodes.Ldnull); - } - break; + yield return Instruction.Create(OpCodes.Ldc_I4, 0x6f); //NumberStyles.Number + var getInvariantInfo = + Context.Body.Method.Module.Import(typeof(CultureInfo)) + .Resolve() + .Properties.FirstOrDefault(pd => pd.Name == "InvariantCulture") + .GetMethod; + var getInvariant = Context.Body.Method.Module.Import(getInvariantInfo); + yield return Instruction.Create(OpCodes.Call, getInvariant); + yield return Instruction.Create(OpCodes.Ldloca, vardef); + var tryParseInfo = + Context.Body.Method.Module.Import(typeof(decimal)) + .Resolve() + .Methods.FirstOrDefault(md => md.Name == "TryParse" && md.Parameters.Count == 4); + var tryParse = Context.Body.Method.Module.Import(tryParseInfo); + yield return Instruction.Create(OpCodes.Call, tryParse); + yield return Instruction.Create(OpCodes.Pop); + yield return Instruction.Create(OpCodes.Ldloc, vardef); + } else { + yield return Instruction.Create(OpCodes.Ldc_I4_0); + var decimalctorinfo = + Context.Body.Method.Module.Import(typeof(decimal)) + .Resolve() + .Methods.FirstOrDefault( + md => md.IsConstructor && md.Parameters.Count == 1 && md.Parameters [0].ParameterType.FullName == "System.Int32"); + var decimalctor = Context.Body.Method.Module.Import(decimalctorinfo); + yield return Instruction.Create(OpCodes.Newobj, decimalctor); + } + break; + case "System.Single": + float outfloat; + if (hasValue && float.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outfloat)) + yield return Instruction.Create(OpCodes.Ldc_R4, outfloat); + else + yield return Instruction.Create(OpCodes.Ldc_R4, 0f); + break; + case "System.Double": + double outdouble; + if (hasValue && double.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outdouble)) + yield return Instruction.Create(OpCodes.Ldc_R8, outdouble); + else + yield return Instruction.Create(OpCodes.Ldc_R8, 0d); + break; + case "System.TimeSpan": + TimeSpan outspan; + if (hasValue && TimeSpan.TryParse(valueString, CultureInfo.InvariantCulture, out outspan)) { + var vardef = new VariableDefinition(Context.Body.Method.Module.Import(typeof(TimeSpan))); + Context.Body.Variables.Add(vardef); + //Use an extra temp var so we can push the value to the stack, just like other cases + yield return Instruction.Create(OpCodes.Ldstr, valueString); + var getInvariantInfo = + Context.Body.Method.Module.Import(typeof(CultureInfo)) + .Resolve() + .Properties.FirstOrDefault(pd => pd.Name == "InvariantCulture") + .GetMethod; + var getInvariant = Context.Body.Method.Module.Import(getInvariantInfo); + yield return Instruction.Create(OpCodes.Call, getInvariant); + yield return Instruction.Create(OpCodes.Ldloca, vardef); + var tryParseInfo = + Context.Body.Method.Module.Import(typeof(TimeSpan)) + .Resolve() + .Methods.FirstOrDefault(md => md.Name == "TryParse" && md.Parameters.Count == 3); + var tryParse = Context.Body.Method.Module.Import(tryParseInfo); + yield return Instruction.Create(OpCodes.Call, tryParse); + yield return Instruction.Create(OpCodes.Pop); + yield return Instruction.Create(OpCodes.Ldloc, vardef); + } else { + yield return Instruction.Create(OpCodes.Ldc_I8, 0L); + var timespanctorinfo = + Context.Body.Method.Module.Import(typeof(TimeSpan)) + .Resolve() + .Methods.FirstOrDefault( + md => md.IsConstructor && md.Parameters.Count == 1 && md.Parameters [0].ParameterType.FullName == "System.Int64"); + var timespanctor = Context.Body.Method.Module.Import(timespanctorinfo); + yield return Instruction.Create(OpCodes.Newobj, timespanctor); + } + break; + case "System.Uri": + Uri outuri; + if (hasValue && Uri.TryCreate(valueString, UriKind.RelativeOrAbsolute, out outuri)) { + var vardef = new VariableDefinition(Context.Body.Method.Module.Import(typeof(Uri))); + Context.Body.Variables.Add(vardef); + //Use an extra temp var so we can push the value to the stack, just like other cases + yield return Instruction.Create(OpCodes.Ldstr, valueString); + yield return Instruction.Create(OpCodes.Ldc_I4, (int)UriKind.RelativeOrAbsolute); + yield return Instruction.Create(OpCodes.Ldloca, vardef); + var tryCreateInfo = + Context.Body.Method.Module.Import(typeof(Uri)) + .Resolve() + .Methods.FirstOrDefault(md => md.Name == "TryCreate" && md.Parameters.Count == 3); + var tryCreate = Context.Body.Method.Module.Import(tryCreateInfo); + yield return Instruction.Create(OpCodes.Call, tryCreate); + yield return Instruction.Create(OpCodes.Pop); + yield return Instruction.Create(OpCodes.Ldloc, vardef); + } else + yield return Instruction.Create(OpCodes.Ldnull); + break; + default: + var defaultctorinfo = typedef.Methods.FirstOrDefault(md => md.IsConstructor && !md.HasParameters); + if (defaultctorinfo != null) { + var defaultctor = Context.Body.Method.Module.Import(defaultctorinfo); + yield return Instruction.Create(OpCodes.Newobj, defaultctor); + } else { + //should never happen. but if it does, this prevents corrupting the IL stack + yield return Instruction.Create(OpCodes.Ldnull); + } + break; } } } diff --git a/Xamarin.Forms.Build.Tasks/NodeILExtensions.cs b/Xamarin.Forms.Build.Tasks/NodeILExtensions.cs index a7fed895..31c1a1a8 100644 --- a/Xamarin.Forms.Build.Tasks/NodeILExtensions.cs +++ b/Xamarin.Forms.Build.Tasks/NodeILExtensions.cs @@ -114,58 +114,100 @@ namespace Xamarin.Forms.Build.Tasks yield return Instruction.Create(OpCodes.Ldc_I4, ParseEnum(targetTypeRef, str, node)); else if (targetTypeRef.FullName == "System.Char") yield return Instruction.Create(OpCodes.Ldc_I4, Char.Parse(str)); - else if (targetTypeRef.FullName == "System.Byte") - yield return Instruction.Create(OpCodes.Ldc_I4, Byte.Parse(str, CultureInfo.InvariantCulture)); + else if (targetTypeRef.FullName == "System.SByte") + yield return Instruction.Create(OpCodes.Ldc_I4, SByte.Parse(str, CultureInfo.InvariantCulture)); else if (targetTypeRef.FullName == "System.Int16") yield return Instruction.Create(OpCodes.Ldc_I4, Int16.Parse(str, CultureInfo.InvariantCulture)); else if (targetTypeRef.FullName == "System.Int32") yield return Instruction.Create(OpCodes.Ldc_I4, Int32.Parse(str, CultureInfo.InvariantCulture)); else if (targetTypeRef.FullName == "System.Int64") yield return Instruction.Create(OpCodes.Ldc_I8, Int64.Parse(str, CultureInfo.InvariantCulture)); + else if (targetTypeRef.FullName == "System.Byte") + yield return Instruction.Create(OpCodes.Ldc_I4, Byte.Parse(str, CultureInfo.InvariantCulture)); + else if (targetTypeRef.FullName == "System.UInt16") + yield return Instruction.Create(OpCodes.Ldc_I4, UInt16.Parse(str, CultureInfo.InvariantCulture)); + else if (targetTypeRef.FullName == "System.UInt32") + yield return Instruction.Create(OpCodes.Ldc_I4, UInt32.Parse(str, CultureInfo.InvariantCulture)); + else if (targetTypeRef.FullName == "System.UInt64") + yield return Instruction.Create(OpCodes.Ldc_I8, UInt64.Parse(str, CultureInfo.InvariantCulture)); else if (targetTypeRef.FullName == "System.Single") yield return Instruction.Create(OpCodes.Ldc_R4, Single.Parse(str, CultureInfo.InvariantCulture)); else if (targetTypeRef.FullName == "System.Double") yield return Instruction.Create(OpCodes.Ldc_R8, Double.Parse(str, CultureInfo.InvariantCulture)); - else if (targetTypeRef.FullName == "System.Boolean") - { + else if (targetTypeRef.FullName == "System.Boolean") { if (Boolean.Parse(str)) yield return Instruction.Create(OpCodes.Ldc_I4_1); else yield return Instruction.Create(OpCodes.Ldc_I4_0); - } - else if (targetTypeRef.FullName == "System.TimeSpan") - { + } else if (targetTypeRef.FullName == "System.TimeSpan") { var ts = TimeSpan.Parse(str, CultureInfo.InvariantCulture); var ticks = ts.Ticks; var timeSpanCtor = - module.Import(typeof (TimeSpan)) + module.Import(typeof(TimeSpan)) .Resolve() .Methods.FirstOrDefault(md => md.IsConstructor && md.Parameters.Count == 1); var timeSpanCtorRef = module.Import(timeSpanCtor); yield return Instruction.Create(OpCodes.Ldc_I8, ticks); yield return Instruction.Create(OpCodes.Newobj, timeSpanCtorRef); - } - else if (targetTypeRef.FullName == "System.DateTime") - { + } else if (targetTypeRef.FullName == "System.DateTime") { var dt = DateTime.Parse(str, CultureInfo.InvariantCulture); var ticks = dt.Ticks; var dateTimeCtor = - module.Import(typeof (DateTime)) + module.Import(typeof(DateTime)) .Resolve() .Methods.FirstOrDefault(md => md.IsConstructor && md.Parameters.Count == 1); var dateTimeCtorRef = module.Import(dateTimeCtor); yield return Instruction.Create(OpCodes.Ldc_I8, ticks); yield return Instruction.Create(OpCodes.Newobj, dateTimeCtorRef); - } - else if (targetTypeRef.FullName == "System.String" && str.StartsWith("{}", StringComparison.Ordinal)) + } else if (targetTypeRef.FullName == "System.String" && str.StartsWith("{}", StringComparison.Ordinal)) yield return Instruction.Create(OpCodes.Ldstr, str.Substring(2)); else if (targetTypeRef.FullName == "System.String") yield return Instruction.Create(OpCodes.Ldstr, str); else if (targetTypeRef.FullName == "System.Object") yield return Instruction.Create(OpCodes.Ldstr, str); - else + else if (targetTypeRef.FullName == "System.Decimal") { + decimal outdecimal; + if (decimal.TryParse(str, NumberStyles.Number, CultureInfo.InvariantCulture, out outdecimal)) { + var vardef = new VariableDefinition(context.Body.Method.Module.Import(typeof(decimal))); + context.Body.Variables.Add(vardef); + //Use an extra temp var so we can push the value to the stack, just like other cases + // IL_0003: ldstr "adecimal" + // IL_0008: ldc.i4.s 0x6f + // IL_000a: call class [mscorlib]System.Globalization.CultureInfo class [mscorlib]System.Globalization.CultureInfo::get_InvariantCulture() + // IL_000f: ldloca.s 0 + // IL_0011: call bool valuetype [mscorlib]System.Decimal::TryParse(string, valuetype [mscorlib]System.Globalization.NumberStyles, class [mscorlib]System.IFormatProvider, [out] valuetype [mscorlib]System.Decimal&) + // IL_0016: pop + yield return Instruction.Create(OpCodes.Ldstr, str); + yield return Instruction.Create(OpCodes.Ldc_I4, 0x6f); //NumberStyles.Number + var getInvariantInfo = + context.Body.Method.Module.Import(typeof(CultureInfo)) + .Resolve() + .Properties.FirstOrDefault(pd => pd.Name == "InvariantCulture") + .GetMethod; + var getInvariant = context.Body.Method.Module.Import(getInvariantInfo); + yield return Instruction.Create(OpCodes.Call, getInvariant); + yield return Instruction.Create(OpCodes.Ldloca, vardef); + var tryParseInfo = + context.Body.Method.Module.Import(typeof(decimal)) + .Resolve() + .Methods.FirstOrDefault(md => md.Name == "TryParse" && md.Parameters.Count == 4); + var tryParse = context.Body.Method.Module.Import(tryParseInfo); + yield return Instruction.Create(OpCodes.Call, tryParse); + yield return Instruction.Create(OpCodes.Pop); + yield return Instruction.Create(OpCodes.Ldloc, vardef); + } else { + yield return Instruction.Create(OpCodes.Ldc_I4_0); + var decimalctorinfo = + context.Body.Method.Module.Import(typeof(decimal)) + .Resolve() + .Methods.FirstOrDefault( + md => md.IsConstructor && md.Parameters.Count == 1 && md.Parameters [0].ParameterType.FullName == "System.Int32"); + var decimalctor = context.Body.Method.Module.Import(decimalctorinfo); + yield return Instruction.Create(OpCodes.Newobj, decimalctor); + } + } else yield return Instruction.Create(OpCodes.Ldnull); if (isNullable) |