From b99cf2ac5b28db2fa936a1a32bf84338b15a4236 Mon Sep 17 00:00:00 2001 From: Muhammad Miftah Date: Fri, 8 May 2026 15:40:41 +1000 Subject: [PATCH 1/5] tentatively fixes a bug when enum members start with the @ symbol due to clashing with C# keyword. --- XObjectsCore/API/XTypedServices.cs | 10 +++++++++- XObjectsTests/LinqToXsdConfigurationTests.cs | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/XObjectsCore/API/XTypedServices.cs b/XObjectsCore/API/XTypedServices.cs index 202593ca..ceba6938 100644 --- a/XObjectsCore/API/XTypedServices.cs +++ b/XObjectsCore/API/XTypedServices.cs @@ -419,7 +419,15 @@ public static string ParseValue(XAttribute attribute, XmlSchemaDatatype datatype var strValue = ParseValue(attribute.Value, attribute.Parent, datatype); var enumFacet = typeDef.RestrictionFacets.GetEnumFacet(strValue); - return enumFacet != null ? enumFacet.Member : strValue; + string enumFacetMemberValue = enumFacet != null ? enumFacet.Member : strValue; + + // some enum values can be C# keywords, and to allow compilation, an '@' symbol is added to the name; + // but when converting back, the '@' symbol needs to be removed so the Enum.Parse method can succeed + if (enumFacetMemberValue.Length > 0 && enumFacetMemberValue[0] == '@') { + return enumFacetMemberValue.Substring(1, enumFacetMemberValue.Length - 1); + } + + return enumFacetMemberValue; } // Kept for backward compatibility with code generated in previous versions. // Current generator does not use this method anymore, as attributes with default properties diff --git a/XObjectsTests/LinqToXsdConfigurationTests.cs b/XObjectsTests/LinqToXsdConfigurationTests.cs index 94c1bab0..649e3b03 100644 --- a/XObjectsTests/LinqToXsdConfigurationTests.cs +++ b/XObjectsTests/LinqToXsdConfigurationTests.cs @@ -6,7 +6,7 @@ namespace Xml.Schema.Linq.Tests; public class LinqToXsdConfigurationTests { [Test] - public void TestSetDefaultVisibility() + public void TestSetDefaultVisibility_EnumValueIsInternal() { var config = new Configuration(); var ns1 = new Namespace() { From d78d484ffb3289440fb3a27a78b9c01850b1099d Mon Sep 17 00:00:00 2001 From: Muhammad Miftah Date: Fri, 8 May 2026 15:49:30 +1000 Subject: [PATCH 2/5] added another test to cover fix in previous commit. --- XObjectsTests/WssApiUseTests.cs | 39 ++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/XObjectsTests/WssApiUseTests.cs b/XObjectsTests/WssApiUseTests.cs index 14298cda..67f1562b 100644 --- a/XObjectsTests/WssApiUseTests.cs +++ b/XObjectsTests/WssApiUseTests.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using System.Xml.Linq; using Microsoft.Schemas.SharePoint; @@ -67,5 +68,41 @@ public void TestUseOfDesignerTypeEnum2() const string expectedValue = nameof(parametersType.ParameterLocalType.DesignerTypeEnum.DataSourceFieldNames); Assert.IsTrue(underlyingValue.Value == expectedValue); } + + /// + /// The purpose of this test is to ensure when getting the value of (which is an enum type), no exceptions occur when parsing and returning + /// the enum string value (which is what happens under the hood with the XObjects API as it invokes ). + /// lower case 'false' does clash with C# keyword. + /// + [Test] + public void TrueFalseTest_EnumValueClashesWithCSharpKeyword() + { + var newF = new Feature(new FeatureDefinition() { + Hidden = TRUEFALSE.@false + }); + + var isHidden = newF.Hidden; + + Assert.NotNull(isHidden); + Assert.AreEqual(isHidden, TRUEFALSE.@false); + } + + /// + /// The purpose of this test is to ensure when getting the value of (which is an enum type), no exceptions occur when parsing and returning + /// the enum string value (which is what happens under the hood with the XObjects API as it invokes ). + /// Upper case 'TRUE' does not clash with C# keyword. + /// + [Test] + public void TrueFalseTest_EnumValueIsNotCSharpKeyword() + { + var newF = new Feature(new FeatureDefinition() { + Hidden = TRUEFALSE.TRUE + }); + + var isHidden = newF.Hidden; + + Assert.NotNull(isHidden); + Assert.AreEqual(isHidden, TRUEFALSE.TRUE); + } } } \ No newline at end of file From 64cc668539a780c6f8fe807cfd617c730f4442ee Mon Sep 17 00:00:00 2001 From: Muhammad Miftah Date: Fri, 8 May 2026 15:50:02 +1000 Subject: [PATCH 3/5] Deleted version element in XobjectsCodegen.csproj - this was preventing publishing new releases as the version number wasn't being updated! --- XObjectsCode/XObjectsCodeGen.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/XObjectsCode/XObjectsCodeGen.csproj b/XObjectsCode/XObjectsCodeGen.csproj index 4c939648..2b08688e 100644 --- a/XObjectsCode/XObjectsCodeGen.csproj +++ b/XObjectsCode/XObjectsCodeGen.csproj @@ -3,7 +3,6 @@ netstandard2.0;net8.0 The $(MSBuildProjectName) provides code generation facilities, and is consumed by the LinqToXsdCore command line tool; use the LinqToXsdCore tool to generate code, and link to the XObjectsCore nuget package to consume the generated code in your shipping app or library. Original Authors: Microsoft Corporation. - 3.2.6 $(VersionSuffix) $(Version)-$(VersionSuffix) preview From 0fd2d1692d68ac4a6264977aaf59595a07411911 Mon Sep 17 00:00:00 2001 From: Muhammad Miftah Date: Fri, 8 May 2026 16:05:27 +1000 Subject: [PATCH 4/5] Updated release notes and version props. --- RELEASENOTES.md | 8 ++++++++ Version.props | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 0df23e31..6ad72ac5 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,5 +1,13 @@ # LinqToXsdCore Release Notes +## Version 3.4.15 +Nuget packages: +* https://www.nuget.org/packages/LinqToXsdCore/3.4.15 +* https://www.nuget.org/packages/XObjectsCore/3.4.15 + * [#88](https://github.com/mamift/LinqToXsdCore/pull/88). + * Fixes a bug which threw an exception when accessing the property getter for an element or attribute whose type is an enum type where the enum value shares the same name with a C# keyword, and thus the string value (ToString) returns a word prefixed with the '@' symbol. + * Fixes an issue with publishing new [XObjectsCodeGen](https://www.nuget.org/packages/XObjectsCodeGen) nuget releases. + ## Version 3.4.14 Nuget packages: * https://www.nuget.org/packages/LinqToXsdCore/3.4.14 diff --git a/Version.props b/Version.props index 96d9aa4b..c851ae6b 100644 --- a/Version.props +++ b/Version.props @@ -1,6 +1,6 @@ - 3.4.14 + 3.4.15 $(VersionSuffix) $(Version)-$(VersionSuffix) From e834937fdf3161b0d8c49d402030c9644f2a3994 Mon Sep 17 00:00:00 2001 From: Muhammad Miftah Date: Fri, 8 May 2026 16:16:21 +1000 Subject: [PATCH 5/5] Potential fix for pull request finding (XTypedServices.ParseValue) "The '@' stripping should only be applied when a facet mapping was found (i.e., when enumFacet != null). As written, if GetEnumFacet(strValue) returns null and the raw XML value begins with '@', this will silently change the value. Also, the equivalent enum parsing overload for XElement (ParseValue(XElement element, ..., typeDef)) still returns enumFacet.Member without stripping '@', so element-backed enum getters can still throw." Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- XObjectsCore/API/XTypedServices.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/XObjectsCore/API/XTypedServices.cs b/XObjectsCore/API/XTypedServices.cs index ceba6938..23dbd5cd 100644 --- a/XObjectsCore/API/XTypedServices.cs +++ b/XObjectsCore/API/XTypedServices.cs @@ -419,11 +419,17 @@ public static string ParseValue(XAttribute attribute, XmlSchemaDatatype datatype var strValue = ParseValue(attribute.Value, attribute.Parent, datatype); var enumFacet = typeDef.RestrictionFacets.GetEnumFacet(strValue); - string enumFacetMemberValue = enumFacet != null ? enumFacet.Member : strValue; + if (enumFacet == null) + { + return strValue; + } + + string enumFacetMemberValue = enumFacet.Member; // some enum values can be C# keywords, and to allow compilation, an '@' symbol is added to the name; // but when converting back, the '@' symbol needs to be removed so the Enum.Parse method can succeed - if (enumFacetMemberValue.Length > 0 && enumFacetMemberValue[0] == '@') { + if (enumFacetMemberValue.Length > 0 && enumFacetMemberValue[0] == '@') + { return enumFacetMemberValue.Substring(1, enumFacetMemberValue.Length - 1); }