private void WriteEnumMethod(EnumMapping mapping) { string methodName = (string)MethodNames[mapping]; List<Type> argTypes = new List<Type>(); List<string> argNames = new List<string>(); argTypes.Add(mapping.TypeDesc.Type); argNames.Add("v"); ilg = new CodeGenerator(this.typeBuilder); ilg.BeginMethod( typeof(string), GetMethodBuilder(methodName), argTypes.ToArray(), argNames.ToArray(), CodeGenerator.PrivateMethodAttributes); LocalBuilder sLoc = ilg.DeclareLocal(typeof(string), "s"); ilg.Load(null); ilg.Stloc(sLoc); ConstantMapping[] constants = mapping.Constants; if (constants.Length > 0) { InternalHashtable values = new InternalHashtable(); List<Label> caseLabels = new List<Label>(); List<string> retValues = new List<string>(); Label defaultLabel = ilg.DefineLabel(); Label endSwitchLabel = ilg.DefineLabel(); // This local is necessary; otherwise, it becomes if/else LocalBuilder localTmp = ilg.DeclareLocal(mapping.TypeDesc.Type, "localTmp"); ilg.Ldarg("v"); ilg.Stloc(localTmp); for (int i = 0; i < constants.Length; i++) { ConstantMapping c = constants[i]; if (values[c.Value] == null) { Label caseLabel = ilg.DefineLabel(); ilg.Ldloc(localTmp); ilg.Ldc(Enum.ToObject(mapping.TypeDesc.Type, c.Value)); ilg.Beq(caseLabel); caseLabels.Add(caseLabel); retValues.Add(GetCSharpString(c.XmlName)); values.Add(c.Value, c.Value); } } if (mapping.IsFlags) { ilg.Br(defaultLabel); for (int i = 0; i < caseLabels.Count; i++) { ilg.MarkLabel(caseLabels[i]); ilg.Ldc(retValues[i]); ilg.Stloc(sLoc); ilg.Br(endSwitchLabel); } ilg.MarkLabel(defaultLabel); RaCodeGen.ILGenForEnumLongValue(ilg, "v"); LocalBuilder strArray = ilg.DeclareLocal(typeof(String[]), "strArray"); ilg.NewArray(typeof(String), constants.Length); ilg.Stloc(strArray); for (int i = 0; i < constants.Length; i++) { ConstantMapping c = constants[i]; ilg.Ldloc(strArray); ilg.Ldc(i); ilg.Ldstr(GetCSharpString(c.XmlName)); ilg.Stelem(typeof(String)); } ilg.Ldloc(strArray); LocalBuilder longArray = ilg.DeclareLocal(typeof(long[]), "longArray"); ilg.NewArray(typeof(long), constants.Length); ilg.Stloc(longArray); for (int i = 0; i < constants.Length; i++) { ConstantMapping c = constants[i]; ilg.Ldloc(longArray); ilg.Ldc(i); ilg.Ldc(c.Value); ilg.Stelem(typeof(long)); } ilg.Ldloc(longArray); ilg.Ldstr(GetCSharpString(mapping.TypeDesc.FullName)); MethodInfo XmlSerializationWriter_FromEnum = typeof(XmlSerializationWriter).GetMethod( "FromEnum", CodeGenerator.StaticBindingFlags, new Type[] { typeof(Int64), typeof(String[]), typeof(Int64[]), typeof(String) } ); ilg.Call(XmlSerializationWriter_FromEnum); ilg.Stloc(sLoc); ilg.Br(endSwitchLabel); } else { ilg.Br(defaultLabel); // Case bodies for (int i = 0; i < caseLabels.Count; i++) { ilg.MarkLabel(caseLabels[i]); ilg.Ldc(retValues[i]); ilg.Stloc(sLoc); ilg.Br(endSwitchLabel); } MethodInfo CultureInfo_get_InvariantCulture = typeof(CultureInfo).GetMethod( "get_InvariantCulture", CodeGenerator.StaticBindingFlags, Array.Empty<Type>() ); MethodInfo Int64_ToString = typeof(Int64).GetMethod( "ToString", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(IFormatProvider) } ); MethodInfo XmlSerializationWriter_CreateInvalidEnumValueException = typeof(XmlSerializationWriter).GetMethod( "CreateInvalidEnumValueException", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(object), typeof(string) } ); // Default body ilg.MarkLabel(defaultLabel); ilg.Ldarg(0); ilg.Ldarg("v"); ilg.ConvertValue(mapping.TypeDesc.Type, typeof(Int64)); LocalBuilder numLoc = ilg.DeclareLocal(typeof(Int64), "num"); ilg.Stloc(numLoc); // Invoke method on Value type need address ilg.LdlocAddress(numLoc); ilg.Call(CultureInfo_get_InvariantCulture); ilg.Call(Int64_ToString); ilg.Ldstr(GetCSharpString(mapping.TypeDesc.FullName)); ilg.Call(XmlSerializationWriter_CreateInvalidEnumValueException); ilg.Throw(); } ilg.MarkLabel(endSwitchLabel); } ilg.Ldloc(sLoc); ilg.EndMethod(); }